Create me a generic Validator class of type T with two abstract methods (check and describe), and a dynamic class implementation that validates a Date by checking it falls within a known year range.

← Generics · Ref: Q1242

When a generic abstract class declares more than one abstract method, the dynamic class extending it must override EVERY abstract method. The compiler refuses partial implementations.

GENERIC ABSTRACT WITH MULTIPLE ABSTRACTS

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

DYNAMIC CLASS WITH ALL OVERRIDES

Every abstract must be supplied an override. Here we instantiate the generic for the Date type and check whether a date falls between two known years:

  appointmentValidator <- () extends Validator of Date as class
    override check()
      -> arg0 as Date
      <- rtn as Boolean: arg0 >= EARLIEST_VALID_DATE and arg0 <= LATEST_VALID_DATE
    override describe()
      -> arg0 as Date
      <- rtn as String: "Date " + $arg0

Each overridden method independently uses the type-substituted parameter (arg0 as Date). Methods can refer to date-specific operators like '>=' that the abstract knows nothing about.

USAGE

  scheduledDate <- 2025-06-15
  stdout.println($appointmentValidator.check(scheduledDate))
  stdout.println(appointmentValidator.describe(scheduledDate))

KEY POINT

The SAME generic class works for ANY type T where the override body can produce sensible behaviour. Use String for label processing, Date for temporal validation, Money for currency checking, Dict for lookup containers — the generic carries no assumptions beyond what its abstract methods require.

See Q1234 for single-method generic extension. See Q197 for extending generics. See Q1235 for capture combined with generic extension.

Example

defines module qa.genericsdeep.validatordatemultimethod

  defines constant

    EARLIEST_VALID_DATE <- 2024-01-01

    LATEST_VALID_DATE <- 2030-12-31

  defines class

    Validator of type T as abstract

      check() as abstract
        -> arg0 as T
        <- rtn as Boolean?

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

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

  defines program

    ValidatorDateDemo()
      stdout <- Stdout()

      appointmentValidator <- () extends Validator of Date as class
        override check()
          -> arg0 as Date
          <- rtn as Boolean: arg0 >= EARLIEST_VALID_DATE and arg0 <= LATEST_VALID_DATE
        override describe()
          -> arg0 as Date
          <- rtn as String: "Date " + $arg0

      scheduledDate <- 2025-06-15
      stdout.println($appointmentValidator.check(scheduledDate))
      stdout.println(appointmentValidator.describe(scheduledDate))

Common mistakes

E07140 — Both abstract methods (check and describe) must be overridden in the dynamic class. Leaving describe unimplemented means the method cannot be resolved at the call site. See ek9 -h E07140 for details.

Incorrect:

override check()
          -> arg0 as Date
          <- rtn as Boolean: arg0 >= EARLIEST_VALID_DATE and arg0 <= LATEST_VALID_DATE

Correct:

override check()
          -> arg0 as Date
          <- rtn as Boolean: arg0 >= EARLIEST_VALID_DATE and arg0 <= LATEST_VALID_DATE
        override describe()
          -> arg0 as Date
          <- rtn as String: "Date " + $arg0
Other ways to ask this
  • Write a generic abstract Validator with two abstract methods, instantiated for Date.
  • Implement a generic Validator that has both a check and a describe method.
  • Show me how to extend a multi-method generic abstract for the Date type.
  • Build a parameterised Validator with check and describe overrides for Date values.

Coming from another language?

Java: anonymous inner class extending Validator<Date> { @Override check, @Override describe }. Kotlin: object : Validator<LocalDate>() { override fun check, override fun describe }. Scala: new Validator[LocalDate] { def check; def describe }. Rust: impl Validator<NaiveDate> for ValidatorImpl { fn check; fn describe }. EK9: dynamic class form with all abstract methods overridden in one expression, parameterised for any type.

Keywords: dynamic class, Validator, abstract, multiple methods, Date, override, generic, of type T