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