Why can I only inject components, not classes, in EK9?
← Dependency Injection · Ref: Q957
EK9 dependency injection (the '!' suffix) only works with abstract component types. Classes, records, functions, and traits cannot be injected. E08160 is raised when you attempt to inject a non-component type.
WHY COMPONENTS ONLY
Components are EK9's managed service layer. The DI container knows how to create, wire, and lifecycle-manage components. Classes are user-constructed objects — the container has no way to manage their lifecycle.
INJECTABLE (component genus)
defines component Logger as abstract log() as abstract -> message as String
NOT INJECTABLE (E08160)
defines class — user-managed objects defines record — data-only aggregates defines trait — interface contracts defines function — callable units
CORRECT PATTERN
notifier as NotificationService! // OK: NotificationService is abstract component
INCORRECT PATTERN
helper as HelperClass! // E08160: HelperClass is a class, not a component
See Q668 for injectable contexts. See Q111 for component basics. See Q672 for program-application linking.
Example
defines module qa.di.componentinjectioncontext defines class <?- A regular class — not a component. Cannot be injected. -?> HelperClass label <- "helper" default HelperClass() getLabel() <- rtn as String: label default operator ? defines component <?- Abstract component — can be injected via DI. -?> NotificationService as abstract sendNotification() as abstract -> recipient as String default operator ? <?- Concrete component implementing the abstract service. -?> EmailNotifier extends NotificationService override sendNotification() -> recipient as String stdout <- Stdout() stdout.println(`Email to ${recipient}`) default operator ? defines application NotifyApp register EmailNotifier() as NotificationService defines program ComponentInjectionDemo() with application of NotifyApp stdout <- Stdout() notifier as NotificationService! notifier.sendNotification("demo-user") stdout.println("Component injection works for abstract components")
Common mistakes
E08160 — Only abstract component types can be injected with '!'. Classes are not managed by the DI container. Use a component for injectable dependencies. See ek9 -h E08160 for details.
Incorrect:
notifier as HelperClass!
Correct:
notifier as NotificationService!
Other ways to ask this
- What triggers E08160 COMPONENT_INJECTION_NOT_POSSIBLE?
- Why does injection with ! fail for class types?
- What types support dependency injection in EK9?
Coming from another language?
Java Spring: @Autowired works on any managed bean. Python: inject anywhere. Go: manual wiring. Rust: no DI framework. EK9: injection limited to abstract components for architectural clarity, E08160 if wrong construct genus.
Keywords: service, genus, component, class, construct, DI, managed, injection, E08160, abstract