As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have a base user class which is responsible for manipulating the basic user information: name, age, location, etc. I want to extend my system with the groups functionality and later with projects and meetings. For example:
class User
{
public function getName() {
...
}
public function getAge() {
...
}
}
And then extend it with groups functionality:
class GroupableUser extends User
{
public function join($groupId) {
...
}
public function leave($groupId) {
}
public function requestGroupInvitation($groupId) {
...
}
public function acceptGroupInvitation($groupId) {
...
}
}
The name GroupableUser seems weird to me, however it does't make sense to add join and leave methods to Group class, because its user that joins and leaves a group, not the other way around.
And later I would have classes like UserThatCanHaveProjects and UserThatCanParticipateInMeetings.
How to name these classes?
And how do you typically deal with these situations?
You can't seem to be able to find a way to name the classes because the hierarchy is not very natural. In reality a user may participate in more than one group and each group may have more than one user. But a user may exist without a group, while there can't be a group without a user. I would say this means users should be a member of a group and addUser and removeUser should be placed in Group. Why? Because a user may not even "know" that he may join or leave a group and be perfectly happy, while there can not be a group that does not "know" that a user may join it.
The capability to participate in groups/meetings and have projects is something that a user might be able to do, but it's not something that defines what a user is. This is a pretty clear sign that modelling these options with additional classes is not a good design choice.
Static approach #1: interfaces
In a statically typed language a simplistic implementation would look something like
interface IGrouppableUser {
public function join(...);
}
class GroupableUser implements IGrouppableUser {
public function join(...) { /* implementation */ }
}
And the consumers of grouppable users would accept IGrouppableUser, allowing you to craft as many classes as necessary. You can also do this in PHP, but as mentioned earlier it's probably not a good design no matter what the language.
As a footnote, I should add that with the addition of traits to the language starting from PHP 5.4 the above scenario can be implemented a bit more conveniently (classes can use a trait instead of implementing an interface, which means you don't need to copy/paste the implementation of join all around the code base). But conceptually it's the exact same approach.
The main disadvantage of this approach is that it does not scale. It might be OK if you only need two or three types of users.
Static approach #2: "not supported" exceptions
If most of the users are grouppable and can have projects then it doesn't make much sense to create a hellish hierarchy of classes; you can just add the necessary members to class User, making it a fat interface:
class GroupableUser implements IGrouppableUser {
private $isGrouppable = true; // default, can be changed at runtime
public function join(...) {
if (!$this->isGrouppable) throw new Exception("User is not grouppable!");
// real implementation
}
}
The main disadvantage of this approach is that it makes the class User appear to unconditionally support a wide range of operations when in fact it does not and as a result can make coding tedious and error-prone (lots of try/catch). It might be OK if the vast majority of users support the vast majority of operations.
Dynamic approach #1: behaviors
It would be much better to conditionally allow User instances to participate in these operations. This means that you need to be able to dynamically attach "behaviors" to User objects, which is fortunately quite easy to do in a dynamically typed language.
I suggest looking up a "behaviors" implementation from an established open-source project, but here's a quick and dirty example:
Behavior base class and sample implementation
abstract class Behavior {
public function provides($name) {
return method_exists($this, $name);
}
public function invoke($target, $name, $arguments) {
array_unshift($arguments, $target);
return call_user_func_array(array($this, $name), $arguments);
}
}
class GrouppableBehavior extends Behavior {
public function join(User $user, $groupName) {
echo "The user has joined group $groupName.";
}
}
Composable (can use behaviors) base class and User implementation
class Composable {
private $behaviors = array();
public function __call($name, $arguments) {
foreach ($this->behaviors as $behavior) {
if ($behavior->provides($name)) {
return $behavior->invoke($this, $name, $arguments);
}
}
throw new Exception("No method $name and no behavior that implements it");
}
public function attach($behavior) {
$this->behaviors[] = $behavior;
}
}
class User extends Composable {}
Test driver
$user1 = new User;
$user2 = new User;
$user1->attach(new GrouppableBehavior);
$user1->join('Test Group'); // works
$user2->join('Test Group'); // throws
See it in action.
The main disadvantages of this approach are that it consumes more runtime resources and that behaviors can only access public members of the classes they are attaching to. In some cases you may find yourself forced to expose an implementation detail that should be private to enable a behavior to work.
Dynamic approach #2: decorators
A variation on behaviors is the decorator pattern:
interface IUser {}
interface IGrouppableUser extends IUser {
public function join(...);
}
class User implements IUser {}
class UserGroupingDecorator implements IGrouppableUser {
private $realUser;
public function __construct(IUser $realUser) {
$this->realUser = $realUser;
}
public function join(...) { /* implementation */ }
/* now you need to implement all IUser methods
and forward the calls to $this->realUser */
/* if IUser exposes bare properties we have a problem! */
}
Using this pattern you can create a UserGroupingDecorator that wraps an IUser at will and pass the decorator to anything that accepts either an IUser or an IGrouppableUser.
The main disadvantage of this approach is that it also does not provide access to the non-public members of User. In addition it rules out exposing bare properties from IUser as there is no way to "forward" bare property accesses from UserGroupingDecorator to $realUser if the properties are also defined on the former -- and you cannot implement IGrouppableUser unless they are indeed defined. This state of affairs can be sidestepped by exposing properties as distinct getter/setter methods, but that means still more code to write.
Thinking in terms of a database-driven web app, I might do this with 5 classes:
1) User
2) Group
3) GroupAssignment
4) GroupInvitation
5) GroupInvitationRequest
Class 3 just maps one User to one Group. Classes 4 and 5 are even more obvious. This setup pretty much matches what you would have in a database anyway. This allows for a good amount of flexibility, as a User could be a member of many groups (or one, or none).
EDIT: Added additional classes based on new information in question.
Groupable would be a good name for interface, Interface should describe an aspect of class, that might be required by instance of some different class. Interfaces are contract between classes.
Just don't stick the "I" in front of it, unless you use hungarian notation for everything. Simply use nouns for class names and adjectives for interfaces.
As for the name of class, I would go with:
class Participant extends User implements Groupable
{
// methods that will be expected by from instance of this class
// by any class that requires an object to have Groupable interfrace
}
Related
This question already has answers here:
What is the point of interfaces in PHP?
(15 answers)
Closed 9 years ago.
Can anybody explain the concept of interfaces with good example. I searched but didn't find a good answer. I'm still confused with these concepts.
I found an example for interface from Internet which is shown below. The code works without the interface with the same output. Then what is the purpose of it? Or is it not the real implementation of interfaces?. I need to move from procedural coding to object oriented programming. It would be better if anyone can explain not in more complex technical words.
<?php
interface IPillage
{
public function emptyBankAccounts();
public function burnDocuments();
}
class Employee
{
public function emptyBankAccounts()
{
echo "Call employees and ask to transfer funds to Swiss bank account";
}
public function burnDocuments()
{
echo "Torch the office suite of the employee";
}
}
class Executive extends Employee implements IPillage
{
public function emptyBankAccounts()
{
echo "Call executive and ask to transfer funds to Swiss bank account";
}
public function burnDocuments()
{
echo "Torch the office suite of the executive";
}
}
$obj1=new Employee();
$obj2=new Executive();
$obj1->emptyBankAccounts();
echo '<br>';
$obj2->emptyBankAccounts();
?>
many languages just allow single inheritance, with the interfaces, you are allow to have a kind of multiple inheritance... you can inherit from a base class and in the same time from many interfaces as well.
For example, you can have many classes like.. human, animal, truck. They are different of course, but they can implement an interface like "movable" with a method called "to move."
In that case i can refere to three differents objects from the optical of a "movable element'. I can say myHuman.move/ myMonkey.move / my Truck.move.. I am sure that I can ask for move to any object that implements the movable interface with out take care about another things that the particular objects can do... To think about an interface I have to think about funcionality that they offer.
Sorry about my english I am from Argentina.
Nicolas Perichon
Interface:
cannot be instantiated.is a special type of abstract class in which all the members do not have any implementations.
enables polymorphism.
A class can implement more than 1 Interfaces.
Normally used for application classes: providing contract for ensuring interactibility.
the aim: making sure something is interchangeable.
A class that implements an Interface need to contain all the implementation, otherwise the compiler will throw an error.
CAN-DO relationship.
e.g. Student CAN enrol, Student CAN submit assignment.
public interface ICanEnrol
{
void Enrol();
}
public interface ICanSubmit
{
void Submit();
}
public class Student : ICanEnrol, ICanSubmit
{
public void Enrol()
{
School.Send("enrolment");
}
public void Submit()
{
School.Send("report");
}
}
public class Employee : ICanEnrol, ICanSubmit
{
public void Enrol()
{
Company.Send("enrolment");
}
public void Submit()
{
Company.Send("report");
}
}
As PraDes wrote, creating an interface creates a sort of contract. That is really the key concept here.
Let's say that you are working on a project with a team of other developers. There are several new classes that need to be written and the team wants to come to a consensus on a common approach / design pattern. Everyone agrees that each of these classes will need a foo method, a bar method and a baz method. The concrete details of how these methods will work is going to be a little bit different in each class. However, they should each have the same signature.
We decide to create an interface which names the methods that each of these classes should have (foo, bar, baz) and what their signatures are (ie what params they take). Now when each of us writes one of these new classes we will "implement" the interface. By declaring that "MyClass" implements "MyInterface" we are now required to implement foo, bar, and baz methods in our class. If we do not, our IDE, our compiler, our runtime environment, etc will throw an error.
I can't seem to get my head around what advantages the strategy pattern offer. See the example below.
//Implementation without the strategy pattern
class Registry {
public function Func1(){
echo 'called function 1';
}
public function Func2(){
echo 'called function 2';
}
}
$client = new Registry();
$client->Func1();
$client->Func2();
//Implementation with strategy pattern
interface registry {
public function printMsg();
}
class Func1 implements registry {
public function printMsg(){
echo 'called function 1';
}
}
class Func2 implements registry {
public function printMsg(){
echo 'called function 2';
}
}
class context {
public function printMsg(Registry $class){
$class->printMsg();
}
}
$client = new context();
$client->printMsg(new Func1());
$client->printMsg(new Func2());
In the above two example what advantages will the strategy pattern will offer and how is it better then the first approach? Why should I use strategy pattern?
The above example code might contain errors please ignore the code.
The intent of the Strategy pattern is to:
Define a family of algorithms, encapsulate each one, and make them interchangeable.
Strategy lets the algorithm vary independently from clients that use it. [GoF:349]
To understand what this means, you have to (emphasis mine)
Consider what should be variable in your design. This approach is the opposite of focusing on the cause of redesign. Instead of considering what might force a change to a design, consider what you want to be able to change without redesign. The focus here is on encapsulating the concept that varies, a theme of many design patterns. [GoF:29]
In other words, strategies are related pieces of code you can plug into a client (another object) at runtime to change its behavior. One reason to do this, is to prevent you from having to touch the client each time a new behavior is added (cf. Open Closed Principle (OCP) and Protected Variation). In addition, when you got sufficiently complex algorithms, putting them into their own classes, helps adhering to the Single Responsibility Principle (SRP).
I find the example in your question somewhat ill-suited to grasp the usefulness of the Strategy Pattern. A Registry should not have a printMsg() method and I cannot make much sense of the example as such. An easier example would be the example I give in Can I include code into a PHP class? (the part where I talk about Strategy begins about halfway down the answer).
But anyway, in your first code, the Registry implements the methods Func1 and Func2. Since we assume these to be related algorithms, let's pretend they really are persistToDatabase() and persistToCsv() to have something to wrap our mind around. Let's also imagine that, at the end of an application request, you call one of these methods from a shutdown handler (the client).
But which method? Well, that depends on what you configured and the flag for that is obviously stored in the Registry itself. So in your client you end up with something like
switch ($registry->persistStrategy)
{
case 'database':
$registry->persistToDatabase();
case 'csv':
$registry->persistToCsv();
default:
// do not persist the database
}
But switch statements like this are bad (cf. CleanCode:37ff). Imagine your customer requests you to add a persistToXml() method. Not only do you have to change your Registry class now to add another method, but you also have to change the client to accommodate for that new feature. That's two classes you have to change, when OCP tell us that our classes should be closed for modification.
One way to improve that would be to add a generic persist() method on the Registry and move the switch/case into it so the client only needs to call
$registry->persist();
That's better but it still leaves us with the switch/case and it still forces us to modify the Registry each time we add a new way to persist it.
Now also imagine your product is a framework used by many developers and they come up with their own persist algorithms. How can they add them? They'd have to extend your class but then they'd also have to replace all the occurrences in the framework where yours was used. Or they just write them into your class, but then they'd have to patch the class each time you provided a new version of it. So that's all a can of worms.
Strategy to the rescue. Since the persist algorithms are the stuff that varies, we will encapsulate them. Since you already know how to define a family of algorithms, I'll skip that part and only show the resulting client:
class Registry
{
public function persist()
{
$this->persistable->persist($this->data);
}
public function setPersistable(Persistable $persistable)
{
$this->persistable = $persistable
}
// other code …
Nice, we refactored the conditional with polymorphism. Now you and all the other developers can set whatever Persistable as the desired Strategy:
$registry->setPersistable(new PersistToCloudStorage);
And that's it. No more switch/case. No more Registry hacking. Just create a new class and set it. The Strategy lets the algorithm vary independently from clients that use it.
Also see
How does the Strategy Pattern work?
https://softwareengineering.stackexchange.com/questions/187378/context-class-in-strategy-pattern
http://sourcemaking.com/design_patterns/strategy for some more explanation.
https://www.youtube.com/watch?v=-NCgRD9-C6o
End Notes:
[GoF] Gamma, E., Helm, R., Johnson, R., Vlissides, J., Design Patterns: Elements of Reusable ObjectOriented Software, Reading, Mass.: AddisonWesley, 1995.
[CleanCode] Martin, Robert C. Clean Code: A Handbook of Agile Software Craftsmanship. Upper Saddle River, NJ: Prentice Hall, 2009. Print.
Basically Strategy is for grouping functionality across multiple classes.
Oh and you have a typo in your code
class context {
public function printMsg(registry $class){
$class->printMsg();
}
}
With the name of the interface of the type hinting.
To be more clear let me show you a small example.
Imagine you have an Iphone and an Android
What's their common point?
One is They are both phones.
you could create an interface like this
interface Telephone {
public function enterNumber();
public function call();
public function sentTextMessage();
}
and implement the interface in each of your telephones:
class Iphone implements Telephone {
// implement interface methods
}
class Android implement Telephone {
}
and you can have a service attached to all phones like a GPS on you car:
and be sure that if you plug a telephone (usually with the interface BlueTooth).
you could do something like this:
class carGps{
public function handFreeCall(Telephone $tel){
$this->amplifyVolume($tel->call());
}
}
$tomtom = new CarGps();
$tomtom->handFreeCall(new Iphone());
//or if you like to:
$tomtom->handFreeCall(new Android());
as an application developer, you'll be able to use your handFreeCall on every phones that implements the Telephone interface without breaking your code, because you'll know that the telephone is capable of calling.
Hope I helped.
Strategy pattern helps in abstracting out the algorithmic approach for doing some particular work. Suppose you want to sort an array of numbers via different algorithms, In this case it is better to apply a strategy pattern than to tightly couple the algorithm with your code.
In the class where you are instantiating the class composed of strategy you instantiate the strategy class reference by passing it to the constructor of composed class.
This way you we are programming to an interface and not implementation and therefore at any point of time we can add more classes to the hierarchy of strategy class and pass the same to the class composed of strategy
Kindly go through the following link
There's a library and a symfony bundle here:
https://packagist.org/packages/pugx/godfather
A couple of important features of the Strategy pattern as envisioned by the Gang of Four are:
It has no conditional statements (so leave out your switch, if, etc conditionals)
It has a Context participant
Most of the advice on the Strategy leaves out the Context participant. You can find five different examples of the Strategy pattern in PHP here: http://www.php5dp.com/category/design-patterns/strategy/
Often, examples are somewhat odd, describing ducks, cats or else.
Here is an example of Strategy Pattern used in displaying alerts. (Extending the Gordon's answer).
1. Interface for the methods, that vary (i.e., alert format in the case):
require_once("initialize/initialize.php");
interface alert{
public function alert($message);
};
2. Methods, that implement alert interface.
class alertBorderBullet implements alert{
public function alert($message){
$alert = "<p style='border:1px solid #eee; padding:4px; padding-left:8px; padding-right:8px; border-left:4px solid #FC0; margin-top:8px; margin-bottom:8px; color:#888'>".$message."</p>";
return $alert;
}
};
class alertOrangeBgnd implements alert{
public function alert($message){
$alert = "<p style='color:#fff; background-color:#ff9c3a; padding:4px; padding-left:8px; padding-right:8px; margin-top:8px; margin-bottom:8px; border-left:4px solid #e471bd;'>".$message."</p>";
return $alert;
}
};
class alertRed implements alert{
public function alert($message){
$alert = "<p style='color:#c11; background-color:#efefef; padding:4px; padding-left:12px; padding-right:8px; margin-top:8px; margin-bottom:8px;'>".$message."</p>";
return $alert;
}
};
3. Messenger, to separate alert method setting and getting from other objects in a project.
class alertMessenger{
protected $_alert;
public function setAlertType(alert $alert){$this->_alert = $alert;}
public function returnAlert($message){return $this->_alert->alert($message);}
};
4. A random project object that will use "alerting" in different ways.
class randomObject{
public $alert;
public function __construct(){
$this->alert = new alertMessenger;
}
// More code here...
};
$randomObject = new randomObject;
$randomObject->alert->setAlertType(new alertRed);
echo $randomObject->alert->returnAlert($message="Red text for critical info");
$randomObject->alert->setAlertType(new alertBorderBullet);
echo $randomObject->alert->returnAlert($message="Border, bullet and pale-color text");
echo $randomObject->alert->returnAlert($message="Repeat, check style permanence");
$randomObject->alert->setAlertType(new alertOrangeBgnd);
echo $randomObject->alert->returnAlert($message="Again, another redefined message style");
randomObject, when initialized (for this case) automatically creates an instance of alertMessanger and makes its methods available. Behaviors can be set and messages echoed.
Other alert formats can be created and used when necessary by setAlertType and then returnAlert.
I'm trying to understand how using interfaces gives me multiple inheritance as I've been googling.
class A
{
function do1(){}
function do2(){}
function do3(){}
}
class B extends A
{
function do4(){}
function do5(){}
function do6(){}
}
class C extends B
{
}
In the above example, class C has all the methods from class A and B. However, class B also has all the methods of class A, which is not necessary desired.
My searches have come up to use interfaces to solve this issue by moving methods to a class and creating interfaces, as below.
interface A
{
function do1();
function do2();
function do3();
}
interface B
{
function do4();
function do5();
function do6();
}
class C implements A, B
{
function do1(){}
function do2(){}
function do3(){}
function do4(){}
function do5(){}
function do6(){}
}
I don't really see how this solves the issue because all the code is in the new class. If I just wanted to use class A as originally, I would have to create a new class that implement interface A and copy the same code to the new class.
Is there something I'm missing?
PHP doesn't have multiple inheritance. If you have PHP 5.4, though, you can use traits to at least avoid every class having to copy code.
interface A {
public function do1();
public function do2();
public function do3();
}
trait Alike {
public function do1() { }
public function do2() { }
public function do3() { }
}
interface B {
public function do4();
public function do5();
public function do6();
}
trait Blike {
public function do4() { }
public function do5() { }
public function do6() { }
}
class C implements A, B {
use Alike, Blike;
}
class D implements A {
use Alike;
// You can even "override" methods defined in a trait
public function do2() { }
}
Note, though, you have to both implement the interface and use the trait (or, of course, provide your own implementation). And C and D are not related at all, except in both implementing the A interface. Traits are basically just interpreter-level copy and paste, and do not affect inheritance.
The first thing to understand about interfaces is that they are NOT used for inheritance. That is a very important thing to understand. If you're trying to make several classes share the same concrete code, that is not what an interface is for.
The second thing to understand is the difference between client code, and service code.
Client code is essentially the "last step" in a sequence of requests for data. A controller or a view in MVC can be considered client code. The model, meanwhile can be considered service code.
Interfaces are intended for client code to enforce consistency in the types of data it gets from services. Or another way to think about it - interfaces are a way for services to make sure they will be compatible with a request from client code. That is ALL they do. They quite literally provide an interface by which data is accessed, not an implementation that multiple classes can share.
So to give you a concrete example:
Client Code - a ProfileViewController class for a user's forum profile
class ProfileViewController
{
public function showProfile(User $user)
{
$user->getProfile();
}
}
Service Code - a User model that retrieves data and passes it on to the client code that is requesting it
class User
{
public function getProfile()
{
$profile = Do some SQL query here or something
return $profile;
}
}
Now suppose later on you decide to break up Users into Members, Administrators, Referees, Moderators, Writers, Editors etc, and that each has their own unique type of profile. (e.g. its own custom query, or data, or what have you)
There are now two problems present here:
You need to guarantee that whatever you pass in there will contain a getProfile() method.
showProfile() will fail if you pass in anything other than a User object.
1 is easy to solve through abstract classes and methods (or through Interfaces). 2 at first sounds easy as well, because you can just make Moderators, Admins, and Members all subclasses of a User base class.
But then what happens when down the road, in addition to USER profiles, you want to have generic profiles for things. Perhaps you want to show profiles of sports players, or even profiles of celebrities. They're not users, but they still have profiles/details pages.
Because they're not users, it may not make any sense to consider them subclasses of User.
So now you're a bit stuck. showProfile() needs to be able to accept more than just a User object. In fact, you don't know what type of object you will ultimately want to pass in there. But at the same time, since you always want to be able to grab $user->getProfile(), anything you pass in there must be generic enough to be passed in, AND implement a concrete getProfile() method.
Solution? Interfaces!!!!!
First some service code
// First define an interface for ANY service object that will have a profile
interface IHasProfile
{
public function getProfile();
}
// Next, define the class for an object that should have a profile. I'll do a bunch for the sake of an example...
class User implements IHasProfile
{
public function getProfile()
{
$profile = Your unique user profile query here
return $profile;
}
}
class Celebrity implements IHasProfile
{
public function getProfile()
{
$profile = Your unique celebrity profile query here
return $profile;
}
}
class Car implements IHasProfile
{
public function getProfile()
{
$profile = Your unique vehicle profile query goes here
return $profile;
}
}
Next, the client code that will use it
class ProfileViewController
{
public function showProfile(IHasProfile $obj)
{
$obj->getProfile();
}
}
And there you have it. showProfile() has now been abstracted enough that it doesn't care what object it gets, it only cares that the object has a public getProfile() method. So now you can create new types of objects to your heart's content, and if they are intended to have profiles, you can just give them "implements IHasProfile" and they will automatically just work with showProfile().
Kind of a contrived example, but it should illustrate at least the concept of interfaces.
Of course, you could just be "lazy" and not typecast the object at all, and thus allowing ANY object to be passed in. But that's a separate topic entirely ;)
Multiple inheritance is possible only for Interfaces!
such as my output for it:
php > interface A{};
php > interface B{};
php > interface C extends A,B{};
php > class D implements C{};
php > $d = new D();
php > echo ($d instanceof A);
1
I created A and B interfaces and C interface extends them.
After we have D class which implements C interface
Finally, I ask if $d object is instanceof A interface, yeah it's true
For the lulz, I try to create E class which extends D and stdclass classes and get error!
php > class E extends D, stdclass{};
PHP Parse error: syntax error, unexpected ',', expecting '{' in php shell code on line 1
Parse error: syntax error, unexpected ',', expecting '{' in php shell code on line 1
Multiple inheritance is not possible in PHP like in many OOP supported languages
See similar topic here. The topic is in AS3 but gives you answer.
To answer particularly about solving using interfaces is answered in the same post here
As told here by #tonicospinelli, it seems that indeed, PHP allows multiple inheritance of interfaces, but it isn't clearly explained, just given an example
The way multiple inheritance works, PHP passes these using Traits that implement Interfaces.
Once you declare a Class implementing a "multi-interface" (1), you may use already defined Traits to assure inheritance is well-performed.
(1): Saying "multi-interface" I mean a class implementing an interface what extends from multiple other interfaces
I would like to have an interface that allows for a generic type
public function persist($object);
But my concrete implementations to have a type
public function persist(User $user);
From what I understand of PHP this is not possible. From an object oriented design point of view could someone explain to me why what I am doing is misguided and wrong.
Edit: I should clarify, I'm aware of type hinting and how it works my question is really trying to understand from an OO perspective where I am going wrong when I want my concrete implementation to take a different type to the interface.
The interface's purpose is to be a contract between classes. An interface would be useless if multiple concrete classes implemented it, but all expected different inputs. By looking at the interface, you would not know what type of inputs that the implementing classes expect, thus making the interface basically useless. You could not interchange different concrete classes that all use the same interface, as they all expect different inputs (have different interfaces).
I could not replace classA with classB with the assurance that they would both work, since they both have the same interface. This would basically make interfaces useless for every OOP pattern known to man.
EDIT EXAMPLE
class CommandList {
public function addCommand(Command $command) {
$this->commands[] = $command;
}
public function runCommands() {
foreach ($this->commands as $command) $command->run($this);
}
}
interface Command {
public function run(CommandList $commandList);
}
class Hop implements Command {
public function run(CommandList $commandList) {
// hop here
}
}
class Skip implements Command {
public function run(CommandList $commandList) {
// skip here
}
}
See how the interface acts as a contract? If you break that contact, then things that implement Command would not be interchangeable.
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 inherit from an abstract class. What I don't understand is: What is the crucial difference between using traits versus interfaces?
I've tried searching for a decent blog post or article explaining when to use one or the other, but the examples I've found so far seem so similar as to be identical.
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).
Interfaces
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
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.
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.
A trait is essentially PHP's implementation of a mixin, and is effectively a set of extension methods which can be added to any class through the addition of the trait. The methods then become part of that class' implementation, but without using inheritance.
From the PHP Manual (emphasis mine):
Traits are a mechanism for code reuse in single inheritance languages such as PHP. ... It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring inheritance.
An example:
trait myTrait {
function foo() { return "Foo!"; }
function bar() { return "Bar!"; }
}
With the above trait defined, I can now do the following:
class MyClass extends SomeBaseClass {
use myTrait; // Inclusion of the trait myTrait
}
At this point, when I create an instance of class MyClass, it has two methods, called foo() and bar() - which come from myTrait. And - notice that the trait-defined methods already have a method body - which an Interface-defined method can't.
Additionally - PHP, like many other languages, uses a single inheritance model - meaning that a class can derive from multiple interfaces, but not multiple classes. However, a PHP class can have multiple trait inclusions - which allows the programmer to include reusable pieces - as they might if including multiple base classes.
A few things to note:
-----------------------------------------------
| Interface | Base Class | Trait |
===============================================
> 1 per class | Yes | No | Yes |
---------------------------------------------------------------------
Define Method Body | No | Yes | Yes |
---------------------------------------------------------------------
Polymorphism | Yes | Yes | No |
---------------------------------------------------------------------
Polymorphism:
In the earlier example, where MyClass extends SomeBaseClass, MyClass is an instance of SomeBaseClass. In other words, an array such as SomeBaseClass[] bases can contain instances of MyClass. Similarly, if MyClass extended IBaseInterface, an array of IBaseInterface[] bases could contain instances of MyClass. There is no such polymorphic construct available with a trait - because a trait is essentially just code which is copied for the programmer's convenience into each class which uses it.
Precedence:
As described in the Manual:
An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is that members from the current class override Trait methods, which in return override inherited methods.
So - consider the following scenario:
class BaseClass {
function SomeMethod() { /* Do stuff here */ }
}
interface IBase {
function SomeMethod();
}
trait myTrait {
function SomeMethod() { /* Do different stuff here */ }
}
class MyClass extends BaseClass implements IBase {
use myTrait;
function SomeMethod() { /* Do a third thing */ }
}
When creating an instance of MyClass, above, the following occurs:
The Interface IBase requires a parameterless function called SomeMethod() to be provided.
The base class BaseClass provides an implementation of this method - satisfying the need.
The trait myTrait provides a parameterless function called SomeMethod() as well, which takes precedence over the BaseClass-version
The class MyClass provides its own version of SomeMethod() - which takes precedence over the trait-version.
Conclusion
An Interface can not provide a default implementation of a method body, while a trait can.
An Interface is a polymorphic, inherited construct - while a trait is not.
Multiple Interfaces can be used in the same class, and so can multiple traits.
I think traits are useful to create classes that contain methods that can be used as methods of several different classes.
For example:
trait ToolKit
{
public $errors = array();
public function error($msg)
{
$this->errors[] = $msg;
return false;
}
}
You can have and use this "error" method in any class that uses this trait.
class Something
{
use Toolkit;
public function do_something($zipcode)
{
if (preg_match('/^[0-9]{5}$/', $zipcode) !== 1)
return $this->error('Invalid zipcode.');
// do something here
}
}
While with interfaces you can only declare the method signature, but not its functions' code. Also, to use an interface you need to follow a hierarchy, using implements. This is not the case with traits.
It is completely different!
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!
Traits are simply for code reuse.
Interface just provides the signature of the functions that is to be defined in the class where it can be used depending on the programmer's discretion. Thus giving us a prototype for a group of classes.
For reference-
http://www.php.net/manual/en/language.oop5.traits.php
An often-used metaphor to describe Traits is Traits are interfaces with implementation.
This is a good way of thinking about it in most circumstances, but there are a number of subtle differences between the two.
For a start, the instanceof operator will not work with traits (ie, a trait is not a real object), therefore you can't use that to see if a class has a certain trait (or to see if two otherwise unrelated classes share a trait). That's what they mean by it being a construct for horizontal code re-use.
There are functions now in PHP that will let you get a list of all the traits a class uses, but trait-inheritance means you'll need to do recursive checks to reliably check if a class at some point has a specific trait (there's example code on the PHP doco pages). But yeah, it's certainly not as simple and clean as instanceof is, and IMHO it's a feature that would make PHP better.
Also, abstract classes are still classes, so they don't solve multiple-inheritance related code re-use problems. Remember you can only extend one class (real or abstract) but implement multiple interfaces.
I've found traits and interfaces are really good to use hand in hand to create pseudo multiple inheritance. Eg:
class SlidingDoor extends Door implements IKeyed
{
use KeyedTrait;
[...] // Generally not a lot else goes here since it's all in the trait
}
Doing this means you can use instanceof to determine if the particular Door object is Keyed or not, you know you'll get a consistent set of methods, etc, and all the code is in one place across all the classes that use the KeyedTrait.
You can consider a trait as an automated "copy-paste" of code, basically.
Using traits is dangerous since there is no mean to know what it does before execution.
However, traits are more flexible because of their lack of limitations such as inheritance.
Traits can be useful to inject a method which checks something into a class, for example, the existence of another method or attribute. A nice article on that (but in French, sorry).
For French-reading people who can get it, the GNU/Linux Magazine HS 54 has an article on this subject.
If you know English and know what trait means, it is exactly what the name says. It is a class-less pack of methods and properties you attach to existing classes by typing use.
Basically, you could compare it to a single variable. Closures functions can use these variables from outside of the scope and that way they have the value inside. They are powerful and can be used in everything. Same happens to traits if they are being used.
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:
Define a base class with event pub/sub code, and then classes which want to offer events can extend it in order to gain the capabilities.
Define a class with event pub/sub code, and then other classes which want to offer events can use it via composition, defining their own methods to wrap the composed object, proxying the method calls to it.
Define a trait with event pub/sub code, and then other classes which want to offer events can 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 :)
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.
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 is a contract that says “this object is able to do this thing”, whereas a trait is giving the object the ability to do the thing.
A trait is essentially a way to “copy and paste” code between classes.
Try reading this article, What are PHP traits?