I\'ve been trying to study up on PHP lately, and I find myself getting hung up on traits. I understand the concept of horizontal code reuse and not wanting to necessarily in
The trait is same as a class we can use for multiple inheritance purposes and also code reusability.
We can use trait inside the class and also we can use multiple traits in the same class with 'use keyword'.
The interface is using for code reusability same as a trait
the interface is extend multiple interfaces so we can solve the multiple inheritance problems but when we implement the interface then we should create all the methods inside the class. For more info click below link:
http://php.net/manual/en/language.oop5.traits.php http://php.net/manual/en/language.oop5.interfaces.php
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
.
That is the biggest difference.
From the Horizontal Reuse for PHP RFC:
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
Public Service Announcement:
I want to state for the record that I believe traits are almost always a code smell and should be avoided in favor of composition. It's my opinion that single inheritance is frequently abused to the point of being an anti-pattern and multiple inheritance only compounds this problem. You'll be much better served in most cases by favoring composition over inheritance (be it single or multiple). If you're still interested in traits and their relationship to interfaces, read on ...
Let's start by saying this:
Object-Oriented Programming (OOP) can be a difficult paradigm to grasp. Just because you're using classes doesn't mean your code is Object-Oriented (OO).
To write OO code you need to understand that OOP is really about the capabilities of your objects. You've got to think about classes in terms of what they can do instead of what they actually do. This is in stark contrast to traditional procedural programming where the focus is on making a bit of code "do something."
If OOP code is about planning and design, an interface is the blueprint and an object is the fully constructed house. Meanwhile, traits are simply a way to help build the house laid out by the blueprint (the interface).
So, why should we use interfaces? Quite simply, interfaces make our code less brittle. If you doubt this statement, ask anyone who's been forced to maintain legacy code that wasn't written against interfaces.
The interface is a contract between the programmer and his/her code. The interface says, "As long as you play by my rules you can implement me however you like and I promise I won't break your other code."
So as an example, consider a real-world scenario (no cars or widgets):
You want to implement a caching system for a web application to cut down on server load
You start out by writing a class to cache request responses using APC:
class ApcCacher
{
public function fetch($key) {
return apc_fetch($key);
}
public function store($key, $data) {
return apc_store($key, $data);
}
public function delete($key) {
return apc_delete($key);
}
}
Then, in your HTTP response object, you check for a cache hit before doing all the work to generate the actual response:
class Controller
{
protected $req;
protected $resp;
protected $cacher;
public function __construct(Request $req, Response $resp, ApcCacher $cacher=NULL) {
$this->req = $req;
$this->resp = $resp;
$this->cacher = $cacher;
$this->buildResponse();
}
public function buildResponse() {
if (NULL !== $this->cacher && $response = $this->cacher->fetch($this->req->uri()) {
$this->resp = $response;
} else {
// Build the response manually
}
}
public function getResponse() {
return $this->resp;
}
}
This approach works great. But maybe a few weeks later you decide you want to use a file-based cache system instead of APC. Now you have to change your controller code because you've programmed your controller to work with the functionality of the ApcCacher
class rather than to an interface that expresses the capabilities of the ApcCacher
class. Let's say instead of the above you had made the Controller
class reliant on a CacherInterface
instead of the concrete ApcCacher
like so:
// Your controller's constructor using the interface as a dependency
public function __construct(Request $req, Response $resp, CacherInterface $cacher=NULL)
To go along with that you define your interface like so:
interface CacherInterface
{
public function fetch($key);
public function store($key, $data);
public function delete($key);
}
In turn you have both your ApcCacher
and your new FileCacher
classes implement the CacherInterface
and you program your Controller
class to use the capabilities required by the interface.
This example (hopefully) demonstrates how programming to an interface allows you to change the internal implementation of your classes without worrying if the changes will break your other code.
Traits, on the other hand, are simply a method for re-using code. Interfaces should not be thought of as a mutually exclusive alternative to traits. In fact, creating traits that fulfill the capabilities required by an interface is the ideal use case.
You should only use traits when multiple classes share the same functionality (likely dictated by the same interface). There's no sense in using a trait to provide functionality for a single class: that only obfuscates what the class does and a better design would move the trait's functionality into the relevant class.
Consider the following trait implementation:
interface Person
{
public function greet();
public function eat($food);
}
trait EatingTrait
{
public function eat($food)
{
$this->putInMouth($food);
}
private function putInMouth($food)
{
// Digest delicious food
}
}
class NicePerson implements Person
{
use EatingTrait;
public function greet()
{
echo 'Good day, good sir!';
}
}
class MeanPerson implements Person
{
use EatingTrait;
public function greet()
{
echo 'Your mother was a hamster!';
}
}
A more concrete example: imagine both your FileCacher
and your ApcCacher
from the interface discussion use the same method to determine whether a cache entry is stale and should be deleted (obviously this isn't the case in real life, but go with it). You could write a trait and allow both classes to use it to for the common interface requirement.
One final word of caution: be careful not to go overboard with traits. Often traits are used as a crutch for poor design when unique class implementations would suffice. You should limit traits to fulfilling interface requirements for best code design.
Other answers did a great job of explaining differences between interfaces and traits. I will focus on a useful real world example, in particular one which demonstrates that traits can use instance variables - allowing you add behavior to a class with minimal boilerplate code.
Again, like mentioned by others, traits pair well with interfaces, allowing the interface to specify the behavior contract, and the trait to fulfill the implementation.
Adding event publish / subscribe capabilities to a class can be a common scenario in some code bases. There's 3 common solutions:
use
the trait, aka import it, to gain the capabilities.How well does each work?
#1 Doesn't work well. It would, until the day you realize you can't extend the base class because you're already extending something else. I won't show an example of this because it should be obvious how limiting it is to use inheritance like this.
#2 & #3 both work well. I'll show an example which highlights some differences.
First, some code that will be the same between both examples:
An interface
interface Observable {
function addEventListener($eventName, callable $listener);
function removeEventListener($eventName, callable $listener);
function removeAllEventListeners($eventName);
}
And some code to demonstrate usage:
$auction = new Auction();
// Add a listener, so we know when we get a bid.
$auction->addEventListener('bid', function($bidderName, $bidAmount){
echo "Got a bid of $bidAmount from $bidderName\n";
});
// Mock some bids.
foreach (['Moe', 'Curly', 'Larry'] as $name) {
$auction->addBid($name, rand());
}
Ok, now lets show how the implementation of the Auction
class will differ when using traits.
First, here's how #2 (using composition) would look like:
class EventEmitter {
private $eventListenersByName = [];
function addEventListener($eventName, callable $listener) {
$this->eventListenersByName[$eventName][] = $listener;
}
function removeEventListener($eventName, callable $listener) {
$this->eventListenersByName[$eventName] = array_filter($this->eventListenersByName[$eventName], function($existingListener) use ($listener) {
return $existingListener === $listener;
});
}
function removeAllEventListeners($eventName) {
$this->eventListenersByName[$eventName] = [];
}
function triggerEvent($eventName, array $eventArgs) {
foreach ($this->eventListenersByName[$eventName] as $listener) {
call_user_func_array($listener, $eventArgs);
}
}
}
class Auction implements Observable {
private $eventEmitter;
public function __construct() {
$this->eventEmitter = new EventEmitter();
}
function addBid($bidderName, $bidAmount) {
$this->eventEmitter->triggerEvent('bid', [$bidderName, $bidAmount]);
}
function addEventListener($eventName, callable $listener) {
$this->eventEmitter->addEventListener($eventName, $listener);
}
function removeEventListener($eventName, callable $listener) {
$this->eventEmitter->removeEventListener($eventName, $listener);
}
function removeAllEventListeners($eventName) {
$this->eventEmitter->removeAllEventListeners($eventName);
}
}
Here's how #3 (traits) would look like:
trait EventEmitterTrait {
private $eventListenersByName = [];
function addEventListener($eventName, callable $listener) {
$this->eventListenersByName[$eventName][] = $listener;
}
function removeEventListener($eventName, callable $listener) {
$this->eventListenersByName[$eventName] = array_filter($this->eventListenersByName[$eventName], function($existingListener) use ($listener) {
return $existingListener === $listener;
});
}
function removeAllEventListeners($eventName) {
$this->eventListenersByName[$eventName] = [];
}
protected function triggerEvent($eventName, array $eventArgs) {
foreach ($this->eventListenersByName[$eventName] as $listener) {
call_user_func_array($listener, $eventArgs);
}
}
}
class Auction implements Observable {
use EventEmitterTrait;
function addBid($bidderName, $bidAmount) {
$this->triggerEvent('bid', [$bidderName, $bidAmount]);
}
}
Note that the code inside the EventEmitterTrait
is exactly the same as what's inside the EventEmitter
class except the trait declares the triggerEvent()
method as protected. So, the only difference you need to look at is the implementation of the Auction
class.
And the difference is large. When using composition, we get a great solution, allowing us to reuse our EventEmitter
by as many classes as we like. But, the main drawback is the we have a lot of boilerplate code that we need to write and maintain because for each method defined in the Observable
interface, we need to implement it and write boring boilerplate code that just forwards the arguments onto the corresponding method in our composed the EventEmitter
object. Using the trait in this example lets us avoid that, helping us reduce boilerplate code and improve maintainability.
However, there may be times where you don't want your Auction
class to implement the full Observable
interface - maybe you only want to expose 1 or 2 methods, or maybe even none at all so that you can define your own method signatures. In such a case, you might still prefer the composition method.
But, the trait is very compelling in most scenarios, especially if the interface has lots of methods, which causes you to write lots of boilerplate.
* You could actually kinda do both - define the EventEmitter
class in case you ever want to use it compositionally, and define the EventEmitterTrait
trait too, using the EventEmitter
class implementation inside the trait :)
For beginners above answer might be difficult, this is the easiest way to understand it:
Traits
trait SayWorld {
public function sayHello() {
echo 'World!';
}
}
so if you want to have sayHello
function in other classes without re-creating the whole function you can use traits,
class MyClass{
use SayWorld;
}
$o = new MyClass();
$o->sayHello();
Cool right!
Not only functions you can use anything in the trait(function, variables, const...). Also, you can use multiple traits: use SayWorld, AnotherTraits;
Interface
interface SayWorld {
public function sayHello();
}
class MyClass implements SayWorld {
public function sayHello() {
echo 'World!';
}
}
So this is how interfaces differ from traits: You have to re-create everything in the interface in an implemented class. Interfaces don't have an implementation and interfaces can only have functions and constants, it cannot have variables.
I hope this helps!
The main difference is that, with interfaces, you must define the actual implementation of each method within each class that implements said interface, so you can have many classes implement the same interface but with different behavior, while traits are just chunks of code injected in a class; another important difference is that trait methods can only be class-methods or static-methods, unlike interface methods which can also (and usually are) be instance methods.