Create me a generic Processor class of type T with an abstract process method, then extend it inline using a dynamic class with String as the type parameter.

← Generics · Ref: Q1234

Generic abstract classes in EK9 use 'of type T' to declare a type parameter. They can be extended INLINE in expression position using a dynamic class with the syntax '() extends ParentName of ConcreteType as class'. The dynamic class overrides the abstract method, with the type parameter T replaced by the concrete type.

GENERIC ABSTRACT CLASS

  Processor of type T as abstract
    process() as abstract
      -> arg0 as T
      <- rtn as String?
    override operator ? as pure
      <- rtn as Boolean: true

DYNAMIC CLASS EXTENSION

The dynamic class is created at the call site:

  instance <- () extends Processor of String as class
    override process()
      -> arg0 as String
      <- rtn as String: "Processed: " + arg0

USAGE

  result <- instance.process("Hello")
  stdout.println(result)

The '() extends Processor of String as class' form parameterises the parent generic with a concrete type AND creates an instance in one expression. This is more concise than declaring a named subclass when only one usage is needed.

See Q642 for generic constructor inference. See Q649 for generic function implementation. See Q194 for generic class basics.

Example

defines module qa.genericsdeep.processorbasic

  defines class

    Processor of type T as abstract

      process() as abstract
        -> arg0 as T
        <- rtn as String?

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

  defines program

    ProcessorDemo()
      stdout <- Stdout()

      instance <- () extends Processor of String as class
        override process()
          -> arg0 as String
          <- rtn as String: "Processed: " + arg0

      result <- instance.process("Hello")
      stdout.println(result)

Common mistakes

E50040 — An abstract generic with abstract methods must be declared 'as abstract'. Using 'as open' implies the methods have bodies that may be overridden, which leads to unresolved type issues when the dynamic class tries to extend it. See ek9 -h E50040 for details.

Incorrect:

Processor of type T as open

Correct:

Processor of type T as abstract
Other ways to ask this
  • Write a generic abstract class with one typed method and provide a dynamic class implementation.
  • Show me how to extend a generic abstract class inline with a concrete type using a dynamic class.
  • Implement a generic Processor of T that I can extend at the use site for a specific type.
  • Create a parameterised abstract class and instantiate it for String.

Coming from another language?

Java: anonymous inner class extending Processor<String> { @Override public String process(String arg) { ... } }. Kotlin: object : Processor<String>() { override fun process(arg: String) = ... }. Scala: new Processor[String] { override def process(arg: String) = ... }. EK9: '() extends Processor of String as class' is the dynamic class form for inline parameterised extension.

Keywords: dynamic class, type parameter, T, of type, abstract, inline, extends, generic