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