What are the rules for when a function can or cannot be extended?
← Function Extension · Ref: Q594
Only abstract functions can be extended. Concrete functions (those with an implementation body) are closed and cannot serve as a base for other functions.
CAN EXTEND: ABSTRACT FUNCTIONS
Functions declared with 'as abstract' can be extended:
Predicate as pure abstract -> item as String <- result as Boolean?
CANNOT EXTEND: CONCRETE FUNCTIONS
Functions with a body cannot be extended:
addOne() as pure -> x as Integer <- rtn as Integer: x + 1 //Cannot write: DoubleAddOne is addOne
SIGNATURE MUST MATCH (E05140)
The extending function must match the abstract function's parameter types, count, and return type. Mismatches produce E05140.
PURITY MUST BE COMPATIBLE
If the abstract function is pure, implementations must be pure (same E05150 rule as classes). If the abstract function is not pure, implementations can be either.
See Q588 for function extension basics. See Q592 for signature mismatch. See Q593 for multi-level chains. See Q595 for pure abstract function constraints.
Example
defines module qa.function.extensionrules defines function //Abstract: CAN be extended Converter as pure abstract -> input as Integer <- output as String? //Implementation 1 DecimalConverter is Converter as pure -> input as Integer <- output as String: $input //Implementation 2 HexConverter is Converter as pure -> input as Integer <- output as String: "0x" + $input //Concrete function: CANNOT be extended doubleIt() as pure -> number as Integer <- result as Integer: number + number defines program FunctionExtensionRulesDemo() stdout <- Stdout() //Abstract function implementations converters <- List() of Converter converters += DecimalConverter converters += HexConverter for converter in converters stdout.println(converter(255)) //Concrete function: used directly stdout.println(`Double 5: ${doubleIt(5)}`)
Common mistakes
E50001 — A pure function cannot call non-pure methods. The 'as pure' contract forbids all side effects. See ek9 -h E50001 for details.
Incorrect:
doubleIt() as pure -> number as Integer <- result as Integer: number + number stdout.println(result)
Correct:
doubleIt() as pure -> number as Integer <- result as Integer: number + number
Other ways to ask this
- When can I extend a function in EK9?
- What functions can be used as a base type?
- Why can't I extend a concrete function?
Coming from another language?
Java: functional interfaces can only have one abstract method. Kotlin: function types are structural, no extension. Rust: no function type inheritance. EK9: only abstract functions can be extended, concrete functions are closed, E05140 for signature mismatch.
Keywords: immutable, purity, E05150, extend, function, extension, E05140, abstract, side-effect, rules, concrete, closed