Why can't I use 'by' delegation inside a trait?
← Classes and OOP · Ref: Q770
The 'by' keyword delegates trait method implementations to a field. This only works in CLASSES, not in traits. Traits define interfaces and optional default implementations — they cannot hold fields or delegate to other objects.
DELEGATION SYNTAX (CLASS ONLY)
MyClass with trait of SomeTrait by myField
This tells the compiler: when SomeTrait methods are called on MyClass, forward them to myField.
WHY NOT IN TRAITS
Traits are stateless contracts. Delegation requires a concrete field to forward to — traits have no fields. Attempting 'by' in a trait is a design error caught at compile time.
THIS EXAMPLE
The Renderable and Loggable traits define contracts. The Formatter class delegates Renderable to its helper field using 'by'. This is the correct pattern — delegation in a class.
COMMON MISTAKE
Developers try to compose traits using 'by'. In EK9, traits compose through 'with trait of' (listing multiple traits) or 'extends' (trait hierarchy), never through delegation.
See Q78 for traits. See Q85 for composition. See Q93 for classes.
Example
defines module qa.classesandoop.traitdelegation defines trait Renderable render() <- rtn as String? Loggable log() <- rtn as String? Combined with trait of Renderable, Loggable defines class RenderHelper with trait of Renderable label <- String() RenderHelper() -> l as String label :=: l override render() <- rtn as String: label default operator ? Formatter with trait of Renderable by helper helper as Renderable? default private Formatter() Formatter() -> h as Renderable require h? helper: h default operator ? defines program ShowDelegation() stdout <- Stdout() helper <- RenderHelper("formatted output") doc <- Formatter(helper) if doc? stdout.println(doc.render())
Common mistakes
E07040 — Adding 'by renderer' to a trait definition attempts delegation inside a trait. Traits have no fields to delegate to — delegation only works in classes. Remove 'by renderer' or move the delegation to a class. See ek9 -h E07040 for details.
Incorrect:
Combined with trait of Renderable by renderer, Loggable
Correct:
Combined with trait of Renderable, Loggable
Other ways to ask this
- What triggers E07040 trait by identifier not supported?
- How does trait delegation with by work in EK9?
- Where can I use the by keyword for delegation?
Coming from another language?
Java: no delegation keyword, manual forwarding methods required. Kotlin: 'by' keyword works on interfaces in class declarations only. Rust: no delegation, use Deref or manual forwarding. Go: struct embedding provides implicit delegation. C#: no delegation keyword. EK9: 'by' delegation in class declarations only, not in traits.
Keywords: class, delegate, field, forward, interface, delegation, composition, by, trait, E07040