Walk me through fixing error E05030 'not open to be extended' for three different cases: extending a closed class, extending a closed function, and extending a built-in type.
← Debugging and Troubleshooting · Ref: Q1254
E05030 'not open to be extended' is raised whenever you try to extend a type that is closed. There are THREE distinct scenarios and each has a different fix.
CASE 1: EXTENDING A CLOSED USER CLASS
Problem: You own the parent class but forgot 'as open':
AuditLogger // CLOSED by default default AuditLogger()
FileAuditLogger extends AuditLogger // E05030 default FileAuditLogger()
Fix: add 'as open' to the parent:
AuditLogger as open // Now extensible default AuditLogger()
CASE 2: EXTENDING A CLOSED USER FUNCTION
Problem: You try to extend a concrete function that is closed:
formatter() // CLOSED by default -> input as String <- rtn as String: input.trim()
upper <- () is formatter as function // E05030 — formatter is closed rtn: input.trim().upperCase()
Fix: add 'as open' to the parent function:
formatter() as open // Now extensible -> input as String <- rtn as String: input.trim()
CASE 3: EXTENDING A BUILT-IN CLOSED TYPE
Problem: Built-in types (List, Dict, Optional, Result, String, Integer) are ALWAYS closed and can never be extended:
StringList extends List of String // E05030 — List is closed
Fix: use COMPOSITION instead — hold the built-in as a field:
StringCollection
items as List of String: List()
add()
-> item as String
items += item
size() as pure <- rtn as Integer: length items
CHOOSING THE RIGHT FIX
- Case 1 and Case 2 are fine to fix with 'as open' IF you own the parent AND inheritance is the right design.
- For Case 3 (built-in types) you MUST use composition. Built-ins are deliberately closed to prevent subclasses from breaking invariants.
- Whenever possible, prefer composition over inheritance even for your own classes.
See Q1043 for the E05030 diagnosis flow. See Q1250 for 'as open' on classes. See Q1252 for 'as open' on functions.
Example
defines module qa.debugging.fixe05030cases defines class AuditLogger as open default AuditLogger() log() -> message as String stdout <- Stdout() stdout.println("[AUDIT] " + message) default operator ? FileAuditLogger extends AuditLogger default FileAuditLogger() override log() -> message as String stdout <- Stdout() stdout.println("[FILE-AUDIT] " + message) default operator ? StringCollection items as List of String: List() of String default StringCollection() add() -> item as String items += item size() as pure <- rtn as Integer: length items default operator ? defines function formatter() as open -> input as String <- rtn as String: input.trim() defines program FixE05030Demo() stdout <- Stdout() logger <- FileAuditLogger() logger.log("case 1: class extension via 'as open'") upper <- () is formatter as function rtn: input.trim().upperCase() stdout.println(`case 2: open function extended dynamically -> ${upper(" ek9 ")}`) collection <- StringCollection() collection.add("case 3: composition") collection.add("holds a List") stdout.println(`case 3: collection size -> ${collection.size()}`)
Common mistakes
E07090 — Built-in types like List are always closed. Attempting to extend them causes a type resolution error because the compiler cannot resolve the extension. Use composition instead. See ek9 -h E07090 for details.
Incorrect:
StringList extends List of String
Correct:
StringCollection
items as List of String: List()
Other ways to ask this
- How do I fix E05030 in EK9?
- Give me three worked examples of fixing E05030.
- The compiler says 'not open to be extended' — show me the fixes.
- Walk me through the three common causes of E05030 and how to resolve each.
Coming from another language?
Java: final keyword closes classes, subclasses can bypass accidentally. Kotlin: closed by default like EK9, use 'open' keyword. Scala: final keyword closes. C#: sealed keyword closes. EK9: E05030 catches all three cases at compile time — no runtime surprise.
Keywords: fix, built-in, E05030, three cases, closed, open, composition, extends