Define an abstract Shape class with an area method, and a concrete Circle subclass.

← Classes and OOP · Ref: Q1180

Abstract classes use 'as abstract' and concrete children override:

  Shape as abstract
    area() as abstract
      <- rtn as Float?
    default operator ?
  Circle extends Shape
    override area()
      <- rtn as Float: ...
    override operator ? as pure
      ...
    default operator

Do NOT use 'default operator' on the abstract parent -- use only 'default operator ?' because abstract types cannot generate all operators. Concrete children use 'default operator' LAST.

See Q103 for abstract classes. See Q116 for default operator.

Example

defines module qa.classesandoop.abstractclassoperators

  defines class

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

      default operator ?

    Circle extends Shape
      radius <- 0.0

      Circle()
        -> radius as Float
        this.radius: radius

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

      override operator ? as pure
        <- rtn as Boolean: radius?

      operator $ as pure
        <- rtn as String: `Circle(radius=${radius})`

  defines program

    AbstractClassOperatorsDemo()
      stdout <- Stdout()

      circle <- Circle(5.0)
      stdout.println(`Area: ${circle.area()}`)
      stdout.println(`IsSet: ${circle?}`)

      //Polymorphism with abstract type
      shapes <- List() of Shape
      shapes += Circle(3.0)
      shapes += Circle(7.5)

      for shape in shapes
        stdout.println(`Shape area: ${shape.area()}`)

Common mistakes

E07130 — Concrete subclasses must implement all abstract methods. Omitting the override triggers E07130.

Incorrect:

      //missing override of area()

Correct:

      override area()
        <- rtn as Float: Float()
Other ways to ask this
  • Write code for an abstract class hierarchy with Shape and Circle
  • I need an abstract Shape with area() and a concrete Circle that provides the implementation
  • In Java I'd use abstract class Shape with abstract double area(). Write the EK9 version
  • Create a Shape/Circle hierarchy showing abstract methods, override, and default operator placement

Coming from another language?

Java: abstract class Shape { abstract double area(); }. Python: class Shape(ABC): @abstractmethod. Rust: trait Shape { fn area(&self) -> f64; }. EK9: Shape as abstract with area() as abstract.

Keywords: abstract, class, circle, shape, override, area, default operator