59

I recently came across Traits in PHP and I'm trying to understand them. During my research I stumbled upon this Stack Overflow question: Traits vs. Interfaces. The accepted answer mentions the following:

An interface defines a set of methods that the implementing class must implement.

When a trait is use'd the implementations of the methods come along too--which doesn't happen in an Interface.

So far so good but this sounds exactly like the difference between an interface and an abstract class to me. So this raises a follow-up question for me:

  • What is the difference between a Trait and an Abstract Class in PHP?

I am aware that I can extend from only one abstract class and on the other hand use any amount of traits. But is this really the only difference? I still don't completely understand traits and its use.

Zoe
  • 27,060
  • 21
  • 118
  • 148
simon
  • 2,896
  • 1
  • 17
  • 22

2 Answers2

73

Traits allow you to share code between your classes without forcing you into a specific class hierarchy. Say you want all your classes to have the convenient utility method foo($bar); without traits you have two choices:

  • implement it individually with code redundancy in each class
  • inherit from a common (abstract) ancestor class

Both solution aren't ideal, each with their different tradeoffs. Code redundancy is obviously undesirable, and inheriting from a common ancestor makes your class hierarchy design inflexible.

Traits solve this problem by letting you implement foo($bar) in a trait which each class can "import" individually, while still allowing you to design your class hierarchy according to business logic requirements, not language necessities.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • 3
    So if I get this right, traits are basically thought for using the same code among several classes that aren't related in any way? – simon Sep 13 '16 at 09:45
  • 6
    Yes, exactly right. Think of it as little bits and pieces that you can use to put a class together from (composition). Depending on how great the code reusability is in your app, you can go as far as implementing everything as a trait and then just combining a handful of traits together into actual classes in various configurations. – deceze Sep 13 '16 at 09:47
  • 2
    Would you say it's like helpers ? – Jeremy Belolo Feb 27 '18 at 13:51
  • 1
    @Jeremy That's probably the most common use case, but is too narrow in itself. As written above, you could compose entire classes purely out of traits, if that makes sense in your case. – deceze Feb 27 '18 at 13:54
  • 2
    You can also use them in combination with interfaces, e.g. define some methods in an interface and provide the implementation with a trait, that way your implementation is more flexible than an abstract class (because its not limited to a single type) – MADforFUNandHappy Sep 09 '20 at 21:29
  • That's true, but sometimes I found necessary to use an abstract class as "glue" for interfaces, their relative implementation traits, and some method that won't fit nicely in a trait (like `__construct`, depending on the coding style that one follows). Ending up with the same limit of the initial abstract. Still, probably there's a way to avoid `abstract` completely. – Kamafeather Oct 30 '20 at 20:46
12

Not exactly... Let's quote official documentation for this purpose:

A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring inheritance.

So Traits are used for composition purposes to enable the class to perform some logic/behavior. If you're inheriting from another/abstract class, it's usually for purposes of polymorphism and you get a distinct inheritance/class hierarchy, which may or may not be desirable.

I think it all depends on the context, on the architecture and on what exactly are you trying to do.

walther
  • 13,466
  • 5
  • 41
  • 67