So ive finally gotten round to playing with traits and they are very handy, the problem that i have been having is that i want to have some traits to add functionality to my data objects.
In of itself this is simple except that in doing so im using methods that are defined in my base data object
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object. I had thought about putting a check in the _addToUpdate method but ideally i would like an error to be shown when creating the instance.
I have come up with a solution that works but makes me feel a bit dirty and is far from ideal
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
abstract protected function _addToUpdate($field, $value);
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
By adding an abstract method to the Extended_Object i then can at least be sure that an error will be show if the method i need in Base_Object isnt present but i am not guaranteed that the method in question will actually do what i want it to do.
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Im hoping that someone has found a way to do this or at least a better solution than mine.
Note: i know that i could do this with a constructor but that would only be viable when using a single trait if i decided at a later date to create anther few object extension traits its going to get very messy very quickly
Edit: i do realize that traits arnt really designed for what im trying to do but they do at least in part allow me to get around the problem of single inheritance and i know im not the only dev planning to use them in this way
Well (IMHO) the problem exists with the way you are using traits which is technically anti-pattern.
First, What are traits and why should I use them:
To quote from one of the comments in php.net
The best way to understand what traits are and how to use them is to
look at them for what they essentially are: language assisted copy
and paste.
If you can copy and paste the code from one class to another (and
we've all done this, even though we try not to because its code
duplication) then you have a candidate for a trait.
Now even that traits lets you use members of the class which is using them, that does not mean you should do that. back to SRP, this is a real violation.
PHP lets you do echo $_POST['XSS data'] but that does not mean you should do it. So, regardless to the way you want to strict your trait usage, what you are actually doing is that you are introducing the issue and you are trying to solve it
so to answer your question, simply redesign your code in order for you not to use class methods and members based on an assumption that each class which will use the trait should have these methods and members.
I think your solution with an abstract function is precisely what that facility is intended for. I agree with your gut feeling:
i am not guaranteed that the method in question will actually do what i want it to do
However, this is the same assumption you make whenever you use an interface: the only thing that is asserted is that a method exists with the correct signature (which in PHP amounts mostly to its name and number of parameters). There is no way to know that the function actually behaves in a particularly useful way when given those parameters.
In the case of a trait, an abstract method is effectively the same kind of contract as an interface: "in order to use this trait, you must provide these pre-requisites".
I would also note that common description of traits is "automated copy and paste", so it should generally be thought of as separate from object hierarchies. More technically, it represents "horizontal code reuse", not "multiple inheritance". For example, you can define a trait that allows a class to implement an interface, but to the outside code, it is the interface that is important, not the trait.
I am faced with a similar problem, however with multiple subclasses inheriting from the base class.
It would make sense at this point to put trait abstract declarations into some sort of include file and as a trait itself, e.g.:
abstract class Base_Object {
use BaseObjectTrait;
...
}
trait BaseObjectTrait {
protected function _addToUpdate($field, $value) {
...
}
}
trait BaseObjectTraitPrototypes {
abstract protected function _addToUpdate($field, $value);
}
trait Extended_Object {
use BaseObjectTraitPrototypes;
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
Can anyone think of a more elegant solution than this? I'm using the term 'prototype' very loosely here from a C programming sense. 'Header' files are likewise from a C programming context but still not ideal. Can anyone think of a more concise concept for the problem domain, something php-fig acceptable perhaps?
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object.
:
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Maybe I'm missing something, but if this trait should only ever be applied to instances of Base_Object, then it sounds as if this "trait" should be a subclass of the Base_Object and not a trait at all?
The User class then extends this Extended_Object (a subclass), rather than useing the Extended_Object (a trait).
From: http://php.net/manual/en/language.oop5.traits.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.
Related
Sorry if this is a duplicate question or a common design principle, I have searched around but was unable to find any answers to this question. I'm probably just searching with the wrong keywords.
I have been looking at a popular library Sabre/Event (https://sabre.io/event/) and in the code there is a simple class/inheritance model that I am trying to understand:
The class EventEmitter implements EventEmitterInterface and uses EventEmitterTrait (see below for code).
There is a comment in EventEmitterTrait above the class which says:
* Using the trait + interface allows you to add EventEmitter capabilities
* without having to change your base-class.
I am trying to understand why this comment says this, and why it allows adding capabilities without changing the base class, and how that is different from just putting the routines into EventEmitter itself.
Couldn't you just extend EventEmitter and add capabilities in the derived class?
Simplified code:
// EventEmitter.php
class EventEmitter implements EventEmitterInterface {
use EventEmitterTrait;
}
// EventEmitterInterface.php
interface EventEmitterInterface {
// ... declares several function prototypes
}
// EventEmitterTrait.php
trait EventEmitterTrait {
// ... implements the routines declared in EventEmitterInterface
}
You're basically asking two questions here.
What are interfaces and why are they useful?
What are traits and why are they useful?
To understand why interfaces are useful you have to know a little about inheritance and OOP in general. If you've ever heard the term spaghetti code before (it's when you tend to write imperative code that's so tangled together you can hardly make sense of it) then you should liken that to the term lasagna code for OOP (that's when you extend a class to so many layers that it becomes difficult to understand which layer is doing what).
1. Interfaces
Interfaces diffuse some of this confusion by allow a class to implement a common set of methods without having to restrict the hierarchy of that class. we do not derive interfaces from a base class. We merely implement them into a given class.
A very clear and obvious example of that in PHP is DateTimeInterface. It provides a common set of methods which both DateTime and DateTimeImmutable will implement. It does not, however, tell those classes what the implementation is. A class is an implementation. An interface is just methods of a class sans implementation. However, since both things implement the same interface it's easy to test any class that implements that interface, since you know they will always have the same methods. So I know that both DateTime and DateTimeImmutable will implement the method format, which will accept a String as input and return a String, regardless of which class is implementing it. I could even write my own implementation of DateTime that implements DateTimeInterface and it is guaranteed to have that method with that same signature.
So imagine I wrote a method that accepts a DateTime object, and the method expects to run the format method on that object. If it doesn't care which class, specifically, is given to it, then that method could simply typehint its prototype as DateTimeInterface instead. Now anyone is free to implement DateTimeInterface in their own class, without having to extend from some base class, and provide my method with an object that's guaranteed to work the same way.
So in relation to your EventEmitter example, you can add the same capabilities of a class (like DateTime) to any class that might not even extend from DateTime, but as long as we know it implements the same interface, we know for sure it has the same methods with the same signatures. This would mean the same thing for EventEmitter.
2. Traits
Traits, unlike interfaces, actually can provide an implementation. They are also a form of horizontal inheritance, unlike the vertical inheritance of extending classes. Because two completely different class that do not derive from the same base class can use the same Trait. This is possible, because in PHP traits are basically just compiler-assisted copy and paste. Imagine, you literally copied the code inside of a trait and just pasted it into each class that uses it right before compile time. You'd get the same result. You're just injecting code into unrelated classes.
This is useful, because sometimes you have a method or set of methods that prove reusable in two distinct classes even though the rest of those classes have nothing else in common.
For example, imagine you are writing a CMS, where there is a Document class and a User class. Neither of these two classes are related in any meaningful way. They do very different things and it makes no sense for one of them to extend the other. However, they both share a particular behavior in common: flag() method that indicates the object has been flagged by a user for purposes of violating the Terms of Service.
trait FlagContent {
public function flag(Int $userId, String $reason): bool {
$this->flagged = true;
$this->byUserId = $userId;
$this->flagReason = $reason;
return $this->updateDatabase();
}
}
Now consider that perhaps your CMS has other content that's subject to being flagged, like a Image class, or a Video class, or even a Comment class. These classes are all typically unrelated. It probably wouldn't make much sense just to have a specific class for flagging content, especially if the properties of the relevant objects have to be passed around to this class to update the database, for example. It also doesn't make sense for them to derive from a base class (they're all completely unrelated to each other). It also doesn't make sense to rewrite this same code in every class, since it would easier to change it in one place instead of many.
So what seems to be most sensible here is to use a Trait.
So again, in relation to your EventEmitter example, they're giving you some traits you can reuse in your implementing class to basically make it easier to reuse the code without having to extend from a base class (horizontal inheritance).
Per Sabre's Event Emitter's docs on "Integration into other objects":
To add Emitter capabilities to any class, you can simply extend it.
If you cannot extend, because the class is already part of an existing
class hierarchy you can use the supplied trait.
So in this case, the idea is if you're using your own objects that already are part of a class hierarchy, you may simply implement the interface + use the trait, instead of extending the Emitter class (which you won't be able to).
The Integration into other objects documentation says:
If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait".
I understand it's a workaround when you already have an OOP design you don't want to alter and you want to add event capabilities. For example:
Model -> AppModel -> Customer
PHP doesn't have multiple inheritance so Customer can extend AppModel or Emitter but not both. If you implement the interface in Customer the code is not reusable elsewhere; if you implement in e.g. AppModel it's available everywhere, which might not be desirable.
With traits, you can write custom event code and cherry-pick where you reuse it.
This is an interesting question and I will try to give my take on it. As you asked,
What is the purpose of using traits to define functions for an interface ?
Traits basically gives you the ability to create some reusable code or functionality which can then be used any where in your code base. Now as it stands, PHP doesn't support multiple inheritance therefore traits and interfaces are there to solve that issue. The question here is why traits though ?? Well imagine a scenario like below,
class User
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
public function name(){}
public function friends(){}
// and a few other methods
}
Now lets say that we have a post class which has the same logic as user and that can be achieved by having hasRatings() and hasBeenFavorited() methods. Now, one way would be to simply inherit from User Class.
class Post extends User
{
// Now we have access to the mentioned methods but we have inherited
// methods and properties which is not really needed here
}
Therefore, to solve this issue we can use traits.
trait UserActions
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
}
Having that bit of logic we can now just use it any where in the code where ever it is required.
class User
{
use UserActions;
}
class Post
{
use UserActions;
}
Now lets say we have a report class where we want to generate certain report on the basis of user actions.
class Report
{
protected $user;
public function __construct(User $user)
{
$this->user = $user
}
public function generate()
{
return $this->user->hasRatings();
}
}
Now, what happens if i want to generate report for Post. The only way to achieve that would be to new up another report class i.e. maybe PostReport.. Can you see where I am getting at. Surely there could be another way, where i dont have to repeat myself. Thats where, interfaces or contracts come to place. Keeping that in mind, lets redefine our reports class and make it to accept a contract rather than concrete class which will always ensure that we have access to UserActions.
interface UserActionable
{
public function hasRatings();
public function hasBeenFavorited();
}
class Report
{
protected $actionable;
public function __construct(UserActionable $actionable)
{
$this->actionable = $actionable;
}
public function generate()
{
return $this->actionable->hasRatings();
}
}
//lets make our post and user implement the contract so we can pass them
// to report
class User implements UserActionable
{
uses UserActions;
}
class Post implements UserActionable
{
uses UserActions;
}
// Great now we can switch between user and post during run time to generate
// reports without changing the code base
$userReport = (new Report(new User))->generate();
$postReport = (new Report(new Post))->generate();
So in nutshell, interfaces and traits helps us to achieve design based on SOLID principles, much decoupled code and better composition. Hope that helps
I am building some classes (in PHP, although this question extends to other OOP languages as well) which hold information from a database. As such, I want to create an Interface: "syncable".
interface syncable{
protected function _pushToDB();
protected function _pullFromDB();
}
The problem I am encountering is that I want "syncable" to also have a method which (probably) never changes and variable to go with:
protected $sync = 0;
public function sync(){
if($this->sync == 0){
// DB in sync with class; Do nothing.
}
if(this->sync == 1){
$this->_pushToDB();
$this->sync = 0;
}
if(this->sync == -1){
$this->_pullFromDB();
$this->sync = 0;
}
}
As variables are changed in an implemented class, or the database is updated elsewhere, the $sync variable is updated to properly reflect the type of sync needed, then sync() can be called at some point which in turn calls the proper implemented method. While _pushToDB() and _pullFromDB() are very specialized per class, sync() will remain constant between most, if not all, classes.
Since the classes implementing "syncable" such as "users", "foo", and "bar" have no real relation to "syncable" and may need to extend other classes, "syncable" should be an interface rather than an abstract class.
So my question is, what is the best way of accomplishing this? Must I copy-paste my sync() function into every class which implements "syncable"? Do I create an abstract class and hope no class which extends "syncable" ever needs to extend anything else? (Since PHP and many OOP don't support multiple-inheritance) Is there some other PHP solution which would better fit this situation? Are there any generic OOP solutions for this problem?
You should have a look at php traits, you can create this traits and then use them whereever you want/need to use them, is a part of the multi-inheritance principle:
http://php.net/manual/en/language.oop5.traits.php
Can you help to clarify PHP Interface for me. I get that the main point is so that multiple classes can implement some of the same functions.
abstract class Plane {
public function openDoors();
}
interface Fliers {
public function fly();
}
now lets use them
class Boeing747 extends Plane implements Fliers {
public function fly() {
// some stuff
}
public function openDoors() {
// do something
}
}
and
class Tweety implements Fliers{
public function fly() {
// some stuff
}
}
In this case both Boeing747 and Tweety can implement the interface Fliers to access the public function fly(). However, in all examples that I am seeing, no functionality is actually defined in the interface, but rather when it is called inside of the class method itself.
Why would I not just define fly() as a separate function in each of Boeing747 and Tweety, instead of using the interface? Can you provide a concrete, basic example where it would be advantageous? Thanks!
It's a technique known as Design by Contract. Essentially, the interface serves as a contract, or a promise that any class that implements the interface will exhibit a particular set of behaviours. It allows your code to check capabilities of an object passed to it without having to worry about details that don't matter in the current context. For example, your openDoors() method could equally apply to a house, an aircraft, a canal lock, a car or anything else with doors, but other than having doors all of these things have very little in common. Even if they do all support the idea of having doors that can be opened, they may actually perform the door opening actions in wildly different ways.
The interface allows you to tell calling code that all these things have doors that you can open, without having to impose any artificial relationship between them when none exists. The instanceof keyword lets you check if an object meets certain criteria (if it's an instance of a particular class or subclass, or if it implements a particular interface).
interface ThingWithDoors {
public function openDoors ();
}
class House implements ThingWithDoors {
// Implement openDoors here
}
class CanalLock implements ThingWithDoors {
// Implement openDoors here
}
class Boeing747 extends Aircraft implements ThingWithDoors {
// Implement openDoors here
}
// Calling code
if ($object instanceof ThingWithDoors) {
// We don't know exactly what class we have, but we do know it has an openDoors method
$object -> openDoors ();
}
You could in theory achieve the same thing with other PHP functionality such as method_exists or Reflection, but those techniques are far from ideal because there's no contract to enforce anything (two different classes could implement door opening but have completely different names for the methods that do it, and you'd have to check for both with method_exists calls). Then, suppose, some other programmer adds a new class to the system that implements door opening in a completely different way from the ones you already check for. All the code where doors could be opened throughout the program would have to be updated to account for this new method too! If you add a new class to the system and it implements the ThingWithDoors interface, however, then all the code that opens doors will automatically work with the new class as it did with the old class without any modification at all (provided the new class implements the interface properly and respects return values that, sadly, aren't enforced by PHP interfaces).
Another nice thing about this for the programmer is that they don't have to keep looking up in the documentation/source code how to invoke certain behaviours in an object. If they know what the ThingWithDoors interface looks like then they know that everything that implements ThingWithDoors can have its doors opened, and that the method call for doing it is always going to be openDoors (). That can save you a fair bit of time as a developer, especially on a big project!
in OO PHP an object can have only one parent class. To see why this is adopted , lets use the Bird Class to show what multiple inheritance is and how it can lead to problems.
If you wanted to create a Wooping_Crane class, it would make sense to derive this class from Bird class. Suppose you also have an Endangered_Species class.
Multiple inheritance would allow you to create a Wooping_Crane class from combination of these two classes( Bird and Endangered classes). This would seem to be an excellent idea until you realize that both classes define an eating behaviour. Which one to prefer? so this is the disadvantage of multiple inheritance.
PHP solves this in two ways : Firstly , using interface - a class with function definition only.
If Endangered_Species were an interface rather than a class, having more than one eating function wouldn't matter. The method definition in the Bird class would act as the implementation of the interface function. In this way interfaces avoid the problem of defining the same function twice.
Secondly, using traits. ou can read about it in other posts.
Is it a good practice to use in the base class a method which will be defined in a derived one? For instance:
abstract class CApplication {
use TSingleton;
protected final function singletonInstanceInit() {
if (php_sapi_name() == 'cli') {
$this->initCLIApp();
}
else {
$this->initWebApp();
}
}
}
abstract class CWebApplication extends CApplication {
protected function initWebApp() { }
}
abstract class CCLIApplication extends CApplication {
protected function initCLIApp() { }
}
AFAIK this is not a good practice.
Inheritance is needed for the purpose of defining new behaviors and new specialized types of objects. Which means that you could/*should* write a base class now and extend it some time late on.
If the base class knows something about the structure of it's derived classes that's somewhat of a contract, the derived classes need to implement some functions in order to work with that base class in which case "design by contract" springs to mind.
If you need to have a certain function in the derived class maybe it should be declared as an abstract function in the base class or as a method in an interface the class implements.
That way it's not unreasonable for the base class to know about methods implemented in the derived classes.
Also AFAIK other stricter languages would not permit this at compiler level. You would really need to do some refactoring to achieve this in c++ or Java something along the lines of what I said above using abstract functions in the base class or interfaces.
What you are talking about is 2 different schools of thought. I've seen ruby developers doing such stuff because they were using mixins (yes lots of gems do that). On other hand if you go and ask a classic Java programmer he won't recommend you doing that. The type of liberty that you are just showing in your code is what only dynamic typed languages give you (Ya I know some heads would nod saying I used CGLib), they are implementable either in a hackish way for static typed languages or they are not used at all.
Long story cut short, if I were you I would look into scenario and decide if I need such black magic for my given task or not? No rule is bad as long as it doesn't hurt the code quality.
I have an application in which a number of objects are all extending an abstract class which defines methods like create() edit() retrieve() and delete(). Since each of the child classes use the same logic for these functions, the abstract class defines that default behaviour, and in the few cases where it needs to be augmented, the child classes can override or use the hooks I've built in.
Now I'm having the situation where some of the child classes need to be made immutable, meaning that they shouldn't have edit() or delete() methods. This need sounds to me like a job for an interface named something like immutable which the immutable classes could implement. Problem is that interfaces don't stop methods from being called, they just enforce a method's existence. So this is obviously not going to work.
Making two parent classes, one for mutable objects and one for immutable ones is ugly and is probably asking for problems down the line which maintenance. I could have the immutable objects override the offending methods with an empty method that did nothing, but that also seems messy and like I'm not doing proper OOP at that point.
So what would you suggest as the best way to allow a large set of classes to all inherit a set of methods, but for some of them to not inherit all of the methods? (The application in question is written php, but general OOP techniques from any language can still be helpful).
create an immutable-base class as a child of the base class.
the immutable-base should implement final overrides of edit() and delete() which do nothing or throw an error.
Final, so that all immutable children are guaranteed not to be able to edit or delete
bonuses of this strategy
easily check if an object is immutable by testing for instanceof immutable-base
easily change objects from immutable and back again by modifing what it extends
Actually creating classes that have empty methods or throw errors is bad - such methods are confusing, they take up space and do nothing.
A better approach would be to make the immutable class the base class and make the mutable class extend it with adding methods for modification. This way each class has only those methods, that really belong there.
I like Java's approach to this. Throw an exception. Create an UnsupportedOperationException and for those implementations that shouldn't use a specific method throw one to let the user know they can't use this functionality for this implementation.
Another thought I wanted to throw out as a possible solution. Classes could implement an interface that looks like the following:
Interface Immutable {
const immutable = true;
}
and then the Base abstract class can write the delete() and edit() methods with
if (!$this->immutable) {
//do_stuff
}
This would also extend well to other classifications of class, like NonDeletable and NonEditable to allow for more fine grained behaviour.
Here is super short workaround, make your method final and start it with:
if(self::class!=static::class) return;#or throw an error
It will not prevent inheritance itself, but methods will not work in children classes (with error or without - is up to you).
As of PHP 5.4, you can use Traits.
For example, you could make a base class that only includes the methods that all child classes have:
class EntityManager {
public function create() {/*...*/}
public function retrieve() {/*...*/}
}
Then you could define a couple of traits:
trait EditTrait {
public function edit() {/*...*/}
}
trait DeleteTrait {
public function delete() {/*...*/}
}
You would then create an immutable child class like this:
class LogManager extends EntityManager {
...
}
And a mutable child class like this:
class ContactManager extends EntityManager {
use EditTrait;
use DeleteTrait;
...
}
Traits have some advantages over some of the other solutions here such as:
No duplication of code.
Single base class.
Methods that don't work or don't make sense, don't appear on classes that don't support them (especially important for docs and apis).