What is the full set of type hierarchy checks EK9 performs?
← Type Hierarchy Constraints · Ref: Q611
EK9 performs comprehensive type hierarchy validation during compilation, catching structural errors that would cause runtime failures in less strict languages.
CIRCULAR HIERARCHIES (E05020)
Detects cycles in inheritance chains at any depth. A class that directly or indirectly extends itself is rejected. Applies to classes, traits, records, and components.
CLOSED TYPE EXTENSION (E05030)
EK9 types are closed by default. Extending a type that is not 'as open' or 'as abstract' produces E05030.
THIS IN WRONG CONTEXT (E05070)
Using 'this' in a standalone function or other context without an instance is rejected with E05070.
OVERRIDE VALIDATION (E05100-E05120)
E05100: claiming override when nothing to override exists. E05110: matching a parent method without 'override' keyword. E05120: method name matches parent but signature differs (shadowing).
PURITY HIERARCHY (E05150-E05160)
E05150: overriding a pure method without marking the override as pure. E05160: super call from a pure method to a non-pure parent.
SEALED TYPE ENFORCEMENT (E05240-E05270)
E05240: concrete type not in 'allow only' list. E05250: abstract type in 'allow only' list. E05260: dispatcher missing handler for permitted type. E05270: sealed class not declared 'as open'.
See Q602 for circular hierarchies. See Q605 for 'this' context. See Q606 for method shadowing. See Q607 for sealed class requirements. See Q570 for override mechanics.
See Q679 for sealed allow-only. See Q680 for diamond trait resolution. See Q697 for inheritance depth limit.
See Q729 for inheritance depth boundary example.
Example
defines module qa.typehierarchy.summary defines trait //Trait hierarchy: clean and valid Loggable logEntry() as abstract <- rtn as String? defines class //Open class: can be extended BaseEntity as open entityId() <- rtn as String: "entity" default operator ? //Extends open class: valid UserEntity extends BaseEntity with trait of Loggable override entityId() <- rtn as String: "user" override logEntry() <- rtn as String: "User entity" default operator ? //Sealed class: open + allow only Status allow only Active, Inactive as open label() <- rtn as String: "status" Active extends Status override label() <- rtn as String: "active" Inactive extends Status override label() <- rtn as String: "inactive" defines function testHierarchySummary() user <- UserEntity() require user.entityId() == "user" require user.logEntry() == "User entity" active <- Active() inactive <- Inactive() require active.label() == "active" require inactive.label() == "inactive"
Common mistakes
E05270 — A sealed class with allow only must be declared as open. Without as open, the class is closed by default and no subclasses can extend it. See ek9 -h E05270 for details.
Incorrect:
Status allow only Active, Inactive
Correct:
Status allow only Active, Inactive as open
E05120 — When overriding entityId from the parent BaseEntity, the override keyword is mandatory. Without it, the compiler detects method shadowing. See ek9 -h E05120 for details.
Incorrect:
entityId()
Correct:
override entityId()
E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.
Incorrect:
require user.entityId().toUpperCase() == "user"
Correct:
require user.entityId() == "user"
Other ways to ask this
- What hierarchy errors can EK9 detect?
- How does EK9 validate type hierarchies?
- What are all the E05xxx hierarchy error codes?
Coming from another language?
Java: some checks at compile time (circular, override), others at runtime. Python: MRO failures at class creation time. C++: compile-time hierarchy checks but no sealed types. Kotlin: comprehensive compile-time checks similar to EK9. Rust: no inheritance, trait coherence rules instead. EK9: all hierarchy checks at compile time, no runtime surprises.
Keywords: E05240, circular, E05020, type, E05030, E05270, inherit, check, validation, E05120, E05070, hierarchy, summary, compile