E07130: not declared abstract but still has abstract methods/operators

Category: E07xxx Full resolution · Reported in phase: FULL_RESOLUTION · Classification: NOT_MARKED_ABSTRACT_BUT_IS_ABSTRACT · All error codes

What went wrong

Your type contains abstract methods but the TYPE ITSELF isn't marked as 'abstract'. Types with abstract methods must be abstract.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 103 (What are abstract classes and methods in EK9?)
  • ek9 -q 108 (How do I implement a trait for my class?)
  • ek9 -q 210 (How does trait delegation with 'by' work in EK9?)

How to fix it

  1. Add 'as abstract' to the class declaration, OR
  2. Implement all the abstract methods, OR
  3. If the abstract methods come from a trait, delegate them: declare a field whose type implements the trait and write 'with trait of <Trait> by <field>' — the compiler auto-forwards every trait method to that field, making the class concrete.

A class with any unimplemented abstract method must be abstract itself unless it delegates (option 3) or implements (option 2) those methods.

Common causes

  • Forgot to mark class as abstract
  • Didn't realize some methods are abstract
  • Incomplete class definition

See also

  • E07130: non-abstract type with abstract methods (this error)
  • E07140: dynamic class missing abstract implementations

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E07130: not declared abstract but still has abstract methods/operators

#!ek9
defines module error.e07130.bad

  defines trait

    //Create a trait with one concrete method and some abstract methods/operators
    T1
      concreteMethod()
        -> count as Integer
        <- rtn as Boolean: count?

      tMethod()
        -> amount as Float
        <- rtn as Boolean?

      operator + as pure
        -> amount as Float
        <- rtn as Float?

  defines class
    //This is valid as a method is abstract and so this class is also abstract
    C1 as abstract
      default C1()

      aMethod() as abstract
        -> count as Integer
        <- rtn as Boolean?

      //A concrete method
      bMethod()
        -> count as Integer
        <- rtn <- true

      //Note that in class, we have to state that this is abstract (unlike traits)
      operator - as pure abstract
        -> amount as Float
        <- rtn as Float?

    //This too is valid
    C2 with trait of T1 as abstract
      default C2()

    //But this is Ok because it marked as abstract
    C3 extends C1 as abstract
      default C3()

    //This is an error, just marking as open is not enough, this is abstract
    //But it is picked up in the SYMBOL_DEFINITION phase and is checked elsewhere.
    //So it is commented out here - but left in place to highlight it is not missing
    <!-
    C4 as open
      default C4()

      aMethod() as abstract
        -> count as Integer
        <- rtn as Boolean?
    -!>

    //This is an error, this is abstract because T1.tMethod is abstract
    C5 with trait of T1
      default C5()

    //This is an error, this is abstract because T1.tMethod is abstract and marking as open makes not difference.
    //So even though the operator is now implemented, this not enough.
    C6 with trait of T1 as open
      default C6()

      override operator + as pure
        -> amount as Float
        <- rtn as Float: amount

    //Another error because C1 is abstract and C7 has not implemented and so must also be marked as abstract.
    C7 extends C1
      default C7()

    //So still an error because the operator is still unimplemented.
    C8 extends C1
      default C8()

      //We now override and implement
      override aMethod()
        -> count as Integer
        <- rtn as Boolean: true

    //So still an error because the aMethod is still unimplemented.
    C9 extends C1
      default C9()

      //We now override and implement
      override operator - as pure
        -> amount as Float
        <- rtn as Float: 0.0

    //Now this will be OK, as everything is implemented.
    C10 extends C1
      default C10()

      override aMethod()
        -> count as Integer
        <- rtn as Boolean: true

      override operator - as pure
        -> amount as Float
        <- rtn as Float: 0.0

    //This is now OK because all abstract method are implemented.
    C11 with trait of T1
      default C11()

      override tMethod()
        -> amount as Float
        <- rtn as Boolean: true

      override operator + as pure
        -> amount as Float
        <- rtn as Float: amount

Fixed: Mark it abstract, or implement every abstract method

#!ek9
defines module error.e07130.good

  defines trait
    Greeter
      greet() as abstract
        <- rtn as String?

  defines class

    //Option 1: say it is abstract
    PartGreeter with trait of Greeter as abstract
      default PartGreeter()

    //Option 2: implement every abstract method
    EnglishGreeter with trait of Greeter
      override greet()
        <- rtn as String: "hello"

Fixed: Delegate the trait's methods to a property

#!ek9
defines module error.e07130.good.delegate

  defines trait
    Greeter
      greet() as abstract
        <- rtn as String?

  defines class

    EnglishGreeter with trait of Greeter
      override greet()
        <- rtn as String: "hello"

    //Concrete: greet() is forwarded to the greeter property
    PoliteGreeter with trait of Greeter by greeter
      greeter as Greeter: EnglishGreeter()

      default operator ?

Questions and answers

These Q&A entries show E07130 and its fix: