What is the maximum inheritance depth allowed in EK9?
← Code Quality · Ref: Q763
EK9 enforces Depth of Inheritance Tree (DIT) limits per construct type. When a hierarchy exceeds the limit, E11019 triggers.
THRESHOLDS
- Class: max DIT of 4
- Record: max DIT of 2
- Trait: max DIT of 4
- Function: max DIT of 3
- Component: max DIT of 4
HOW DIT IS COUNTED
DIT counts the number of extends relationships from the root to the leaf. The implicit Any base is not counted. So Level1 -> Level2 -> Level3 -> Level4 -> Level5 has DIT = 4.
THIS EXAMPLE
The class hierarchy below has exactly DIT = 4 (5 levels including root). This is the maximum allowed. Adding Level6 extending Level5 would trigger E11019.
WHY LIMIT DEPTH
- Research by Chidamber and Kemerer: classes with DIT > 5 have disproportionately more defects
- Deep hierarchies create fragile base class problems
- Each level adds coupling — changes ripple through all descendants
- Prefer composition over deep inheritance
HOW TO REDUCE DEPTH
1. Use composition/delegation instead of inheritance
2. Use traits for shared behaviour without hierarchy depth
3. Flatten by extracting common fields into records
See Q310 for code quality overview. See Q315 for inheritance limits. See Q729 for boundary testing.
Example
defines module qa.codequality.inheritanceboundary defines class <?- 5-level class hierarchy with DIT = 4 (exactly at class threshold). Level1 (root) -> Level2 -> Level3 -> Level4 -> Level5 (leaf) Each level must be 'as open' to allow extension, except the leaf. -?> Level1 as open value1 as Integer: 1 getSum() <- rtn as Integer: value1 default operator ? Level2 extends Level1 as open value2 as Integer: 2 override getSum() <- rtn as Integer: value2 default operator ? Level3 extends Level2 as open value3 as Integer: 3 override getSum() <- rtn as Integer: value3 default operator ? Level4 extends Level3 as open value4 as Integer: 4 override getSum() <- rtn as Integer: value4 default operator ? //DIT = 4, exactly at threshold — this compiles Level5 extends Level4 value5 as Integer: 5 override getSum() <- rtn as Integer: value5 default operator ? defines program InheritanceDepthDitDemo() stdout <- Stdout() leaf <- Level5() stdout.println(`Sum: ${leaf.getSum()}`)
Common mistakes
E11019 — Adding Level6 extending Level5 pushes the hierarchy depth from 4 to 5, exceeding the class threshold of 4. Use composition instead of deeper inheritance. See ek9 -h E11019 for details.
Incorrect:
Level5 extends Level4 as open value5 as Integer: 5 override getSum() <- rtn as Integer: value5 default operator ? Level6 extends Level5 value6 as Integer: 6 override getSum() <- rtn as Integer: value6 default operator ? defines program
Correct:
Level5 extends Level4 value5 as Integer: 5 override getSum() <- rtn as Integer: value5 default operator ? defines program
Other ways to ask this
- What triggers E11019 excessive inheritance?
- How deep can I extend classes in EK9?
- What is the DIT limit for classes?
- Why does EK9 limit inheritance depth?
Coming from another language?
Java: no DIT limit (Spring hierarchies often 6-8 deep). C#: no DIT limit (NDepend advisory only). C++: no limit (MFC hierarchies notoriously deep). Kotlin: no DIT limit. Python: no limit. EK9: DIT exceeding threshold is a compiler error.
Keywords: hierarchy, E11019, DIT, composition, inheritance, extends, depth, boundary, open, class, quality