Register a concrete Logger as an abstract Logger type for dependency injection.

← Dependency Injection · Ref: Q1183

Register concrete as abstract, inject with the abstract type:

  register ConsoleLogger() as Logger
  ...
  logger as Logger!

The '!' suffix marks an injection point. Injection fields MUST use the abstract type (Logger!), not the concrete type (ConsoleLogger!). The compiler validates a matching registration exists.

See Q1110 for DI basics. See Q227 for compile-time validation. See Q228 for ordering.

Example

defines module qa.di.abstractrequired

  defines component

    Logger as abstract
      log() as abstract
        -> message as String
        <- output as String?

      default operator ?

    ConsoleLogger is Logger
      override log()
        -> message as String
        <- output as String: `[INFO] ${message}`

      default operator ?

  defines application

    LoggingApp
      register ConsoleLogger() as Logger

  defines program

    DiAbstractRequiredDemo() with application of LoggingApp
      stdout <- Stdout()

      //Inject with the ABSTRACT type, not the concrete type
      logger as Logger!

      result <- logger.log("Service started")
      stdout.println(result)

      result2 <- logger.log("Processing request")
      stdout.println(result2)

Common mistakes

E08210 — Every injection point (!) must have a matching registration. The compiler rejects missing registrations with E08210.

Incorrect:

      //no registration

Correct:

      register ConsoleLogger() as Logger
Other ways to ask this
  • Write code to wire a concrete component to its abstract interface for DI
  • I need to register ConsoleLogger as Logger and inject Logger into a program
  • In Spring I'd define @Component ConsoleLogger implements Logger. Write the EK9 DI equivalent
  • Set up application registration of a concrete type as its abstract parent for injection

Coming from another language?

Spring: @Autowired Logger logger (interface). Guice: bind(Logger.class).to(ConsoleLogger.class). .NET: services.AddSingleton<ILogger, ConsoleLogger>(). EK9: register ConcreteType() as AbstractType, inject with AbstractType!.

Keywords: abstract, register, application, concrete, DI, inject, component