Why can't an abstract method have a body in EK9?

← Classes and OOP · Ref: Q768

Abstract methods declare a signature that subclasses must implement. Providing a body contradicts the meaning of abstract — if you provide an implementation, it is not abstract.

ABSTRACT METHOD RULES

1. Mark the method 'as abstract' — no implementation body
2. The containing class must be 'abstract' or 'as open'
3. Subclasses must override and provide the implementation

THIS EXAMPLE

The Shape class below is abstract with one abstract method (area) and one concrete method (describe). The Circle subclass overrides area() with an actual implementation. This is the correct pattern.

COMMON MISTAKE

AI and developers migrating from other languages sometimes write 'as abstract' on a method and then add a body. EK9 treats this as error E07100 because abstract and implementation are mutually exclusive.

HOW TO FIX

1. Remove 'as abstract' if you want the method to have an implementation
2. Remove the body if you want the method to be abstract

See Q93 for defining classes. See Q84 for making classes extensible. See Q86 for abstract classes. See Q274 for common AI mistakes.

Example

defines module qa.classesandoop.abstractmethods

  defines function

    Transformer() as abstract
      -> input as String
      <- output as String?

    UpperTransformer() extends Transformer
      -> input as String
      <- output as String: input.upperCase()

  defines class

    Shape as abstract
      name <- String()

      Shape()
        -> n as String
        name :=: n

      area() as abstract
        <- rtn as Float?

      validate() as abstract
        -> input as String

      describe()
        <- rtn as String: name

      default operator ?

    Circle extends Shape
      radius <- Float()

      Circle()
        -> r as Float
        super("circle")
        radius :=: r

      override area()
        <- rtn as Float: radius * radius * 3.14159

      override validate()
        -> input as String
        require input?

      default operator ?

  defines program

    ShowShapes()
      stdout <- Stdout()
      circle <- Circle(5.0)
      if circle?
        stdout.println("Shape: " + circle.describe())
        circle.validate("test")
        result <- UpperTransformer("hello")
        stdout.println(result)

Common mistakes

E07100 — Adding an initialisation value '0.0' to the return variable creates a method body. Abstract methods must have no implementation — just a signature with unset return type. Remove the initialisation or remove 'as abstract'. See ek9 -h E07100 for details.

Incorrect:

      area() as abstract
        <- rtn as Float: 0.0

Correct:

      area() as abstract
        <- rtn as Float?

E07100 — Adding a require statement creates a body. Even a single precondition check is an implementation. Abstract methods must be pure signatures — the subclass provides the body including any preconditions. See ek9 -h E07100 for details.

Incorrect:

      validate() as abstract
        -> input as String
        require input?

Correct:

      validate() as abstract
        -> input as String

E07100 — Initialising the return variable in an abstract function creates a body. Abstract functions must declare an unset return type — the implementing function provides the logic. See ek9 -h E07100 for details.

Incorrect:

    Transformer() as abstract
      -> input as String
      <- output as String: input

Correct:

    Transformer() as abstract
      -> input as String
      <- output as String?

E07020 — Combining 'override' with 'as abstract' is contradictory. Override means 'I am implementing this', abstract means 'I am NOT implementing this'. Choose one: override with a body, or abstract without. See ek9 -h E07020 for details.

Incorrect:

      override area() as abstract
        <- rtn as Float?

Correct:

      override area()
        <- rtn as Float: radius * radius * 3.14159
Other ways to ask this
  • What triggers E07100 abstract but body provided?
  • How do I define abstract methods in EK9?
  • What is the difference between abstract and concrete methods in EK9?

Coming from another language?

Java: abstract methods have no body, concrete methods have body — same rule but Java uses braces. Python: raise NotImplementedError() convention for abstract, or abc.abstractmethod decorator. Rust: trait methods without default body are abstract. Kotlin: abstract fun has no body, regular fun has body. C#: abstract methods have no body, virtual methods have body. EK9: same semantics as Java/Kotlin, 'as abstract' modifier with no body allowed.

Keywords: override, method, class, implement, E07100, subclass, concrete, signature, body, abstract