Back to results for “Dependency injection”
PHP › Traits

How do traits compare to interfaces combined with composition, in terms of achieving code reuse, and when might one approach be architecturally preferable to the other?

Advanced

Answer

Traits solve a fundamentally different problem than interfaces, since a trait directly provides actual reusable method implementations that get copied into a using class, whereas an interface only defines a contract of method signatures without any actual implementation, meaning that achieving code reuse through composition, meaning a class holding a reference to a separate helper object and delegating certain calls to it, keeps functionality more clearly encapsulated in its own distinct object with an explicit, controllable relationship, while traits offer more convenient direct reuse but can make it harder to trace exactly where a specific method's actual implementation lives when reading a class that uses several different traits together.
// Composition approach
class Order {
    public function __construct(private Logger $logger) {}
    public function log(string $msg) { $this->logger->log($msg); }
}
Real-world example A team debates whether to add logging capability to several classes through a shared trait or through composition with an injected Logger object, ultimately choosing composition specifically because it keeps the logging dependency explicit and easily replaceable through constructor injection.

Common follow-ups: What is the well known software design principle sometimes summarized as favoring composition over inheritance, and how does it relate to this same choice with traits?;Can traits and composition reasonably be combined together within the same class design?