E08150: dependency injection of a non-abstract component is not allowed, use an abstract base component

Category: E08xxx Pre-IR checks (flow analysis) · Reported in phase: FULL_RESOLUTION · Classification: COMPONENT_INJECTION_OF_NON_ABSTRACT · All error codes

What went wrong

You're injecting a CONCRETE component type, but EK9's injection system works with abstract components for flexibility.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 111 (What are components in EK9?)
  • ek9 -q 227 (How does EK9 validate dependency injection at compile time?)
  • ek9 -q 231 (How do programs connect to applications for dependency in...)
  • ek9 -q 228 (Why does registration order matter in EK9 applications?)
  • ek9 -q 229 (How does EK9 prevent circular dependencies?)

Rationale

Abstract injection separates contract from implementation. Different applications can wire different concrete components to the same abstract type (e.g., prod vs test configurations).

How to fix it

  1. Define abstract base component
  2. Inject abstract type with '!'
  3. Register concrete in application with 'register ... as ...'

Common causes

  • Injecting implementation instead of abstraction
  • Not using abstract component pattern

See also

  • E08150: injecting concrete component (this error)
  • E08160: injection not possible in context

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E08150: dependency injection of a non-abstract component is not allowed, use an abstract base component

#!ek9
defines module error.e08150.bad

  defines function

    report()
      <- summary as String?
      timekeeper as Timekeeper!
      summary: "It is " + timekeeper.now()

  defines component

    Timekeeper
      now()
        <- time as String: "noon"

Fixed: Make the concrete component directly; inject only an abstract one

#!ek9
defines module error.e08150.good.fix

  defines function

    report()
      <- summary as String?
      timekeeper <- Timekeeper()
      summary: "It is " + timekeeper.now()

  defines component

    Timekeeper
      now()
        <- time as String: "noon"

Fixed: Inject the abstract component; the application registers the concrete one

#!ek9
defines module error.e08150.good

  defines component

    Timekeeper as abstract
      now() as abstract
        <- time as String?

    NoonTimekeeper is Timekeeper
      override now()
        <- time as String: "noon"

  defines application

    TimeApp
      register NoonTimekeeper() as Timekeeper

  defines program

    Report() with application of TimeApp
      timekeeper as Timekeeper!
      Stdout().println("It is " + timekeeper.now())

Questions and answers

These Q&A entries show E08150 and its fix: