What are abstract classes and methods in EK9?
← Classes and OOP · Ref: Q103
Abstract classes define incomplete types that must be extended with concrete implementations. They can have both implemented and abstract methods, and they can hold state (properties).
ABSTRACT CLASSES
Mark a class as abstract with 'as abstract':
Formatter as abstract prefix <- String() format() as abstract -> text as String <- rtn as String?
Abstract classes cannot be instantiated directly (E50080) — they are incomplete types. 'as abstract' implies 'as open' — you never need both.
WHICH CONSTRUCTS SUPPORT AS ABSTRACT?
Five constructs support 'as abstract': functions, records, classes, components, and traits. Abstract functions are unique to EK9 among mainstream languages. A method without a body must be declared 'as abstract' (E07110).
ABSTRACT METHODS
Abstract methods have no body. Subclasses must provide implementations using the mandatory 'override' keyword:
override format() -> text as String <- rtn as String: prefix + data
Omitting 'override' triggers E05120. The compiler ensures all abstract methods are implemented — omitting any triggers E07140.
ABSTRACT FUNCTIONS
EK9 also supports abstract functions:
defines function Parser as abstract -> input as String <- result as String?
Concrete functions extend abstract ones with 'is' or 'extends'.
WHEN TO USE ABSTRACT VS TRAIT
Use abstract class when: you need shared state (properties), constructors, and partial implementation with a single inheritance chain.
Use trait when: you need pure behaviour contracts that multiple unrelated classes can implement. EK9 supports multiple traits but single class inheritance.
See Q102 for 'as open'. See Q101 for closed by default. See Q51 for abstract functions. See Q106 for traits. See Q110 for trait vs abstract comparison. See Q111 for components. See Q263 for factory pattern returning abstract class implementations. See Q560 for purity contracts on abstract methods. See Q570 for override mechanics. See Q580 for constructor delegation in class hierarchies.
Example
defines module qa.oop.abstractclasses defines function Parser as pure abstract -> input as String <- result as String? JsonParser is Parser as pure -> input as String <- result as String: "parsed:" + input defines class Formatter as abstract prefix <- String() Formatter() -> prefix as String this.prefix: prefix format() as abstract -> text as String <- rtn as String? prefix() as pure <- rtn as String: prefix default operator ? BracketFormatter extends Formatter BracketFormatter() super("[") override format() -> text as String <- rtn as String: `${prefix()}${text}]` default operator ? HtmlFormatter extends Formatter tag <- "p" HtmlFormatter() -> tag as String super(`<${tag}>`) this.tag: tag override format() -> text as String <- rtn as String: `${prefix()}${text}</${tag}>` default operator ? defines program AbstractDemo() stdout <- Stdout() // === ABSTRACT CLASS with concrete subclass === bracket <- BracketFormatter() stdout.println(bracket.format("hello")) html <- HtmlFormatter("div") stdout.println(html.format("content")) // === ABSTRACT FUNCTION === result <- JsonParser("data") stdout.println(result) // === Polymorphism === formatters <- List() of Formatter formatters += BracketFormatter() formatters += HtmlFormatter("span") for formatter in formatters stdout.println(formatter.format("test"))
Common mistakes
E05120 — When implementing an abstract method from a parent class, the 'override' keyword is mandatory. Omitting it on BracketFormatter's format() triggers E05120. See ek9 -h E05120 for details.
Incorrect:
format()
Correct:
override format()
E50010 — Only abstract or open classes can be extended. Abstract classes like Formatter are automatically open. Extending a closed class triggers E50010 — not open to be extended. See ek9 -h E50010 for details.
Incorrect:
BracketFormatter extends SomeClosedClass
Correct:
BracketFormatter extends Formatter
E07110 — A method without a body must be declared 'as abstract'. Omitting the modifier triggers E07110 — implementation not provided so must be declared as abstract. See ek9 -h E07110 for details.
Incorrect:
format()
-> text as String
<- rtn as String?
Correct:
format() as abstract -> text as String <- rtn as String?
E50020 — A class cannot extend a function because they are different construct types (genus). Classes extend classes and functions extend functions. See ek9 -h E50020 for details.
Incorrect:
BracketFormatter extends JsonParser
Correct:
BracketFormatter extends Formatter
E07130 — BracketFormatter extends abstract Formatter but must implement all abstract methods. Removing the override of format() leaves the abstract method unimplemented, triggering E07130 — all abstract methods must be implemented in concrete subclasses. See ek9 -h E07130 for details.
Incorrect:
default operator ?
Correct:
override format() -> text as String <- rtn as String: `${prefix()}${text}]` default operator ?
E50080 — Abstract classes cannot be instantiated directly — they are incomplete types with unimplemented methods. Attempting to call Formatter() triggers E50080 — cannot make a call on an abstract function/type directly. Create a concrete subclass instead. See ek9 -h E50080 for details.
Incorrect:
fmt <- Formatter()
Correct:
bracket <- BracketFormatter()
E50040 — An abstract method can only exist inside an abstract class. If the class is not marked 'as abstract' but contains an abstract method, E50040 is triggered — cannot be abstract in a non-abstract construct. Either mark the class 'as abstract' or provide a method body. See ek9 -h E50040 for details.
Incorrect:
Formatter as open prefix <- String()
Correct:
Formatter as abstract prefix <- String()
E50080 — Abstract classes cannot be instantiated directly — they are incomplete types with unimplemented methods. Attempting to call Formatter() triggers E50080 — cannot make a call on an abstract function/type directly. Create a concrete subclass instead. See ek9 -h E50080 for details.
Incorrect:
html <- Formatter("div")
Correct:
html <- HtmlFormatter("div")
Other ways to ask this
- How do I create an abstract class in EK9?
- How do abstract methods work in EK9?
- When should I use abstract vs trait in EK9?
Coming from another language?
Java: abstract class with abstract methods, can have state and constructors, single inheritance. Python: ABC with @abstractmethod decorator, no enforcement at parse time. Rust: no abstract classes, use traits with default implementations. Go: no abstract types, interfaces are implicitly implemented. Kotlin: abstract class with abstract members, can have state, single inheritance. EK9: 'as abstract' modifier, abstract methods with no body, abstract functions (unique), automatically open for extension, subclasses use 'override'.
Keywords: open, component, method, concrete, class, abstract, virtual, trait, implement, incomplete, override, state, record, hierarchy, function, is, extends, object-oriented