PHP traits have been introduced into the language since the version 5.4.0 in 2008 to encourage horizontal code reuse. Around that year up to 2012, a lot articles and forum discussions rose on the subject. Many people were busy with what exactly is their use and what's the difference with interfaces. I wish I could write on how to create and use them but they have been a lot talks about it too. Besides, creating a trait is as simple as creating any class. In this post my focus will be on why, where and when to use traits. For the purpose of this post, let's have a first glance at what is called a trait for those who are still fresh into the new PHP.
<?php
trait traitName {
// attributes
private $sex;
// methods
public function getSex()
{
return $this->sex;
}
}
To use it, all you have to do is to use
it in any class like this:
class foo{
use traitName;
// class members
}
This will copy all the body of the trait into foo
class. At the end the class would be like this:
class foo{
// attributes
private $sex;
// methods
public function getSex()
{
return $this->sex;
}
// class members
}
The trait can be used by as many as possible classes. Because, they basically play the role of copy and paste.
In this post I am not going to talk much about how to use them because the manual and the rfc have explained that quite well. Instead, I am going to discuss mainly the use traits
. Why use them? Interface or trait? dependency injection or trait? where are traits the most appropriate?
Object Oriented Programming
All is about OOP. The concept of traits has been introduced in PHP OOP. Object Oriented Programming paradigm has a principle called object composition over class inheritance to encourages code reuse. Even though inheritence also allows code reuse, PHP uses single class inheritance model, so a class can only inherite from one and only super class. In case you want a class to inherite from many classes, you would have to chain them like class B extends A
, class C extends B
, etc. And in time this can become very cumbersome. Here is where interfaces and traits come in to laverage the work.
Why traits ?
As mentioned above, traits are meant to enable horizontal code reuse by solving the problem of code reuse limitation with single inheritance. But aside that the traits can be used for following:
- Build conceptual clean class hierarchies
- Easy code maintainability
- To solve most composition problems such as precedence order, conflicts resolutions
What is the difference between traits and interface?
These two concepts are not the same even somehow many people tend to compare them. I agree in sameway they all come into the game for the same purpose of class composition, and code reuse but the are strictly different.
They are both like classes but the declaration key words are different
A class
<?php
class className{
// class body
}
An interface
<?php
// note the key word
interface interfaceName{
// interface body
}
A trait
<?php
// note the key word
trait traitName{
// trait body
}
You can't instantiate a class or an interface on its own
<?php
// You can't do this:
$sth = new interfaceName;
$sth2 = new traitName;
An interface is implemented or extended by another class/interface, while a trait is used another class/trait
<?php
class A implements interfaceName{
// class body
}
interface B extends interfaceName{
// interface B body
}
class B{
// class body
use traitName;
}
A class can at the same time implement an interface and use traits
class A implements interfaceName{
// class body
use traitName;
}
You can't use a trait inside an interface, the same way you can't implement/extend an interface on a trait
Never try this, it's useless and PHP will warn you:
<?php
interface interfaceName{
// interface body
use traitName;
}
// OR
trait traitName implements interfaceName{
// interface body
use traitName;
}
// OR
trait traitName extends interfaceName{
// interface body
use traitName;
}
Interface methods don't have body while the ones in a trait have
When declaring a method in interfaces, they must not have their bodies defined. But methods are fully defined inside Traits.
Interfaces force classes to define its method while traits don't
An interface says to all classes implementing it "these are methods I want you to have. It's my law. If you want your object to abide to it, then just add this method. But get your own way of explaining it to them".
While methods in a trait must be fully defined in the trait then there copied(precedence order applied) in all classes using the trait.
Full example of how you can use these two concepts:
<?php
// Interface
interface interfaceName{
public function articleOne();
}
// trait
trait crime{
public function murder()
{
echo '<br> I am innocent';
}
}
/**
* Normal class representing an object
*/
class ClassName implements interfaceName
{
// calling in
// making the murder() method
// available in this class now
// unlike the interface methods,
// we don't have to repeat trait methods,
// which keeps the code clean
use crime;
// must follow the interface law
public function articleOne()
{
echo 'All human beings are born free and equal in dignity and rights.';
// example of how a method from
// the trait can be used
$this->murder();
}
// method to overwritten the one in trait
// Comment this method out and see what happens
// this is called **precedence order**
public function murder()
{
echo'<br> Murder is a very serious crime deserving harsh punishment for purposes of retribution!';
}
}
// Using the class
/* **************************** */
$classObj = new className();
$classObj->articleOne();
// Another example of how a method from
// the trait can be used
$classObj->murder();
When exactly to use a trait?
This is what really pushed me to think of digging more about traits. In most tutorials I saw and even PHP manual, all example where specific to a problem. That doesn't allow a learner to know when exatly he could think of using traits. This means you have to face the same problem before thinking of using traits.
Beside, those problems case they used, if you don't know them, you will never understand what they are talking about. It's a wrong approach.
I think it would be better someone says where exactly, in which context one could use traits. And here is my take.
Terms used in a programming languages are usually used to fit the most the use context. The key word Trait like many other were chosen based on that too. And when you check the meaning of this word, it simply means a feature, a characteristic line on something. When you look at the word in French, where the word is written the same way it even gives deeper meaning. And the word can be used in sentences like:
-- Un trait physique. Meaning: physical characteristic, or physical nature - A feature on the appearance
-- Un trait caracteristique. Meaning: A characteristical character - A character or specific habit.
-- Un trait rouge. Meaning: A red line.
You can notice this word has to do with objects more than classes. OOP is deeply focused on object than classes defining those objects. Let's find out some context where traits can be used:
-- A trait is a feature we can add or sometimes, remove without altering the basic nature of the object - this is for easy maintenance
-- A trait can be behavioral, physical, or or an attribution - many objects can have it
-- The trait doesn't necessary have anything to do with the basic form/nature of the object
-- We can take care of a trait or the object differently without having to alter any of them - this is clean code
-- A trait is a line - which shows the concept of horizontal code reuse.
When you face a situation where you can sense those signs, think of traits.
Some people think there is no worth using traits when it comes to clean code, but rather we should go for dependency injection. I say, wrong. It's when you think OOP is all about a game of classes you consider dependency inject as the only weapon. When you start thinking of objects rather than classes, then you will really grab the use of traits. Traits could not been created for nothing.
We can inject food in a human being. It's a dependency for him. He needs food to live and function. The same type of food can be injected into another human being as well. That is a perfect case for dependency injection.
But having a scar, or being short or tall is a trait. It's a feature on a specific human being. And this same feature can be applied to different human being.
Conclusion
From now look around you and you will see how many times people have been mis-using Traits. For many it's just a copy & past tool. This is how I understand traits in PHP. I hope this helps you see a bit deeper in them or this opens doors to some other explanations. You may have your own way of understanding them. I would like you to share it with us by commenting under this tutorial.
Thanks for reading this post through out. If you liked it, please share it with your friends.
Last updated 2024-01-11 UTC