I was just playing around with traits to see what its purpose was and I noticed it allows a class to make use of multiple trait classes whereas a class extending from an abstract can extend from one abstract at a time
Here is my example:
trait parentClass
{
public function sayHello()
{
return 'parentClass sayHell() printed';
}
}
trait parentSecondClass
{
public function sayGoodbye()
{
return 'parentClass sayGoodbye() printed';
}
}
class People
{
use parentClass;
use parentSecondClass;
}
$o = new People();
echo $o->sayHello() . '<br/>';
echo $o->sayGoodbye();
Is this the general use of traits?
Generally traits are used for abstract functionality that might be needed by many classes that are not part of the same class hierarchy. You could use a trait to keep this functionality in a single location and apply it across a number of classes.
This doesn't remove the usefulness of abstract classes, but it does potentially remove the need for static utility classes one might typically put these type of functions in.
Related
Since I've just jumped from another language to PHP, I would like to ask you what would be a correct way of adding an extension to a class. My config right now is as follows:
class A extends B {
use C;
public function a(){
}
}
I need to add some additional functions to class A, but logically divide them from it, so I though I would be using a trait C.
So my question is - can I use function a() in my trait C? I know I can define abstract function a() in trait C, however I believe that wouldn't be a good practice at all. Maybe I can somehow inject this into a trait or is it a bad practice as well?
It is possible, the choice is a discretion of the developer, the best solution is based on experience.
trait C {
public function hello() {
parent::a();
echo 'World!';
}
}
class B {
function a() {
echo "hello";
}
}
class A extends B{
use C;
}
(new A())->hello(); // helloWorld!
Let's say:
Class B {
public function a () {
//Does something
}
}
Class A extends B {
//We got access to B's public function. If you want to execute B's a and add some more content, then
public function a() {
parent::a();
//Some more content
}
}
Traits were developed due to PHP's nature of not allowing to inherit from multiple classes (Single inheritance). By creating a trait and apply it to a class, you know inherit it's methods
http://php.net/manual/en/language.oop5.traits.php
It really comes down to your needs.
Q: Do you want to create an interface and make other classes implement certain methods?
A: Create an interface
Q: Do you want to create an abstract class with some implementations and allow other classes to use them? A: Create an abstract class
Q: Do you want a class to inherit from two other classes and they've got different functionalities? A: Create a trait
The best approach is to use the tools at your disposal in order to output your desired result and keeping it organized
While this question is about methods of solving this problem, I am particularly interested in good clean OO design and solutions that conform to current PHP best practices. Thanks in advance for taking a look.
I have the following interface:
<?php
interface Tool {
/**
* Return the unique name of the tool
*/
public function getName();
}
The majority of classes that implement this interface in my project looks like this:
<?php
class Drill implements Tool {
protected $toolName = 'drill';
public function getName() {
return $this->toolName;
}
}
And so the problem is I have dozens of classes that repeat this logic, duplicating the $toolName property and getName() logic, breaking the simple rule of 'Don't repeat yourself'
One solution I have considered is the following:
<?php
abstract class BaseTool implements Tool {
public function getName() {
return $this->toolName;
}
}
Then simply have tool classes extend the abstract BaseTool class:
<?php
class Drill extends BaseTool {
protected $toolName = 'drill';
}
However this now means that I lose the ability to force implementing classes to define the function getName() if they extend the BaseTool class, which can lead to incorrect implementations.
I also think that by having the BaseTool class return $this->toolName, it is making assumptions about the implementing classes and breaks encapsulation.
I have used a simple example to demonstrate the problem but hope you get what I'm trying to solve, and that this problem may also relate to more complex situations. Appreciate your thoughts.
If you're using PHP 5.4.0+, check out traits!
You could create a ToolInterfaceTrait that just contains the getters / setters for the variable $toolName
Your attempt looks good. Nothing more to say.
However this now means that I lose the ability to force implementing classes to define the function getName() if they extend the BaseTool class, which can lead to incorrect implementations.
You still force them, they need to inherit a class which implements them or implement them on their own.
If it is not feasible that all classes which should implement Tool extend from BaseTool, feel free to create more base classes which implement getName() or implement it directly, like you wish.
Btw, if you plan that all tools should extend BaseTool, then the interface isn't necessary at all, at least not for this use case. Interfaces are used for situations where not all classes which are expeted to implement it are inherited from the same base class.
How to avoid duplicating implemented getter function in PHP
Abstract classes are often used to group duplicated code. You're on the right path. As for your doubts about the choice...
However this now means that I lose the ability to force implementing classes to define the function getName() if they extend the BaseTool class, which can lead to incorrect implementations.
By extending the BaseTool class, a class inherits getName() (that's the idea with defining it in the abstract class). I'm not sure why that leads to incorrect implementations or why you'd have to "force implementing classes to define it." They get it automatically by extending the abstract class.
I also think that by having the BaseTool class return $this->toolName, it is making assumptions about the implementing classes and breaks encapsulation.
It might be cleaner if you define the toolName in the abstract class, and you set its value in the constructor?
<?php
abstract class BaseTool implements Tool {
protected $toolName;
public function __construct($toolName)
{
$this->toolName = $toolName;
}
public function getName() {
return $this->toolName;
}
}
You define a constructor in the extended class to put its name:
<?php
class Drill extends BaseTool {
public function __construct()
{
parent::__construct("drill");
}
}
I can't seem to find a good thread explaining this, but are traits in PHP the same (more or less) as structs in C++? I understand the basic syntax for the traits for PHP as well as some more intermediate structs for C++, but are they used in the same way or does PHP have different standards for their use than C++?
Also, since there seems to be no public/private differences such as C++ (where a class is default private until 'public:' or 'protected:' is specified whereas a struct is public until 'private:' or 'protected:' is specified), or is the same general rules?
A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring inheritance.
trait Hello
{
function sayHello() {
echo "Hello";
}
}
trait World
{
function sayWorld() {
echo "World";
}
}
class MyWorld
{
use Hello, World;
}
$world = new MyWorld();
echo $world->sayHello() . " " . $world->sayWorld(); //Hello World
Basically Traits are introduced to avoid some problems in case of inheritance, These are the common problems in class or interface like
Problem in class:
In a traditional you are not allowed to create abstract methods and class can not be inherited by another class if it is inheriting any other class.
Problem in Abstract class:
In Abstract class you can create abstract method as well body methods but whenever a class will inherit this abstract class, it will have to define the body of all abstract methods of the abstract class. Also this abstract class can not be inherited by another class if it is inheriting any other class same as a normal class.
Problem in Interface:
By using interface you can achieve multiple inheritance in class in PHP but in an interface you are not allowed to define any body of a method. You can only have abstract methods and whenever you are going to implement this in a class, you have to define body of all methods.
A trait is a partial class implementation (i.e., constants,
properties, and methods) that can be mixed into one or more existing
PHP classes. Traits work double duty: they say what a class can do
(like an interface), and they provide a modular implementation (like a
class).
"Modern PHP",978-1-491-90501-2, Page 17
It's not quite like structs, a train is a socalled addon or a plugin to a class, meanwhile a struct is more like a collection object.
When you use a trait, it is basically injected into the class, something similar in c++ is multiple inheritance.
<?php
trait MyTrait {
protected $myField;
public function setMyField($value){
return $this->myField = $value;
}
public function getMyField(){
return $this->myField;
}
}
?>
<?php
class MyClass
{
use MyTrait;
}
$myClass = new MyClass();
$myClass->setMyField("Hello World");
echo $myClass->getMyField();//echo's Hello World
While I have been developing objects for PHP for some time now, abstract classes are somewhat new to me. From my understanding, I would use an abstract class when I want to define a list of methods I want myself or other developers to follow, while also providing some base methods to build upon.
It appears there is no way to define properties within an abstract class however, which I find odd. Take the following code:
abstract class Gateway {
abstract public function process();
public function set_gateway_key( $key ) {
$this->key = $key;
}
}
A key of this sort is something you would typically want to restrict access to in order to run through some kind of validation. You could probably imagine some other scenarios as well. However, you are forced to rely on the developer extending this abstract class to set this access modifier.
Am I missing something? Or is there no way to do this?
Abstract classes can have properties.
abstract class AbstractClass {
protected $key;
public function setKey($key) {
$this->key = $key;
}
}
While doing some tutorials on Decorator pattern, I've encountered two different implementations.
Implementation 1 (referred to as I1)
Implementation 2 (referred to as I2)
In short,
I1's parent decorator class implements original object's interface (In the example, class PropertyDecorator implements PropertyInterface. The original object Property implements PropertyInterface as well).
I2's parent decorator class DOES NOT implement original object's interface (In the example, Decorator_Wrapper does not implements Cupcake interface. In fact, there is not even CupcakeInterface at all).
My question is,
Is this merely a personal preference of understanding and implementing Decorator pattern? or one is wrong and one is right?
Just depends on your needs.
Let's see:
Abstract class
Can provide abstract methods.
Can provide real functions and variables.
Can be extended. But a class can extend only 1 parent.
Interface
Can provide abstract methods.
A class may implement several interfaces.
I generally would prefer using a base abstract class, because I can declare some basic functions as well, since you could have a lot of different types of decorators with similar functionality. Methods can be overriden anyways + you can implement some interfaces.
class Decorator extends Decorator_Wrapper implements Interface1, Inteface2 {
public function __construct(){
parent::__construct() ; // Here you could perform some basic decorator actions. It is an advantage compared to interfaces.
}
}
The Decorator pattern is used when you wish to extend the functionality of an instance of a class without extending the class itself (thus, not affecting other instances of said class).
It's kind of an extension at runtime and it's pretty useful since it lets you customize the behavior of an object at runtime. You can even "simulate" multiple inheritance with it.
Since both your examples accomplish this, both are correct. There is no need for a decorator to implement the base interface or extend the original object.
HOWEVER...
If the decorator does not implement the base interface, it MIGHT not be able to be used interchangeably with the original class.
Which might defeat the purpose of using the decorator if you can't use it everywhere "safely".
Example:
interface FooInterface {
public function scare();
}
class Foo implements FooInterface {
protected $boo = 'boo';
public function scare() { echo $this->boo; }
}
class FooBar {
public function __construct(FooInterface $foo) {
$this->foo = $foo;
}
public function scareAlot() {
echo strtoupper($this->foo->scare());
}
}
class INeedFoo {
public static function gimmeFoo(FooInterface $foo) {}
}
$foo = new Foo();
$fooBar = new FooBar($foo);
INeedFoo::gimmeFoo($foo); //Works
INeedFoo::gimmeFoo($fooBar); //Does not Work
Also, if you implement the base interface or extend the base class it might be easier to add multiple decorators on top of eachother but ... you may also end up with a lot of replicated functionality.