I have a few standard classes:
abstract class Parent {}
class Child1 extends Parent {}
class Child2 extends Parent {}
The Parent class contains logic common to both child classes, but each child class has its own additional logic.
For each of my clients, this logic can be configurable. So for any particular client, I may have:
abstract class ClientParent {}
class ClientChild1 extends ClientParent {}
class ClientChild2 extends ClientParent {}
The problem I'm having is how to get the logic from the standard classes into these ones. The first approach would be something like this:
abstract class ClientParent extends Parent {}
Okay, now I have the standard parent logic in all my client-specific classes. Great. But the child classes are already extending ClientParent, so we can't do the same thing for them. My "solution" is then to do this:
abstract class Parent {}
class Child1 extends ClientParent {}
class Child2 extends ClientParent {}
abstract class ClientParent extends Parent {}
class ClientChild1 extends Child1 {}
class ClientChild2 extends Child2 {}
There; now all the appropriate logic is passed down and everybody's happy. Except that now my standard classes are coupled to a particular client. As I have many clients, this is obviously no good.
What's my out here? Is there a way to address this through inheritance alone, or should I look into more complex configuration injection strategies?
Edit:
I'm using PHP 5.3, so I am unable to use traits to solve this problem.
PHP does not support multiple inheritance which is what I think you are trying to approximate here. It does however support (as of 5.4) traits, which in many cases can provide you with comparable functionality.
trait ParentTrait {
public function someUsefulMethod(){/*...*/};
public function someOtherUsefulMethod(){/*...*/};
}
abstract class ClientParent(){}
class ClientChild1 extends ClientParent {
use ParentTrait;
}
$clientChild1 = new ClientChild1();
$clientChild1->someUsefulMethod();
Another option would be to use composition instead, possibly for your problem employing the Strategy pattern would work.
class SuperWidget extends Widget{
private $dataStrategy;
public function __construct(DataStrategy $strategy){
$this->dataStrategy = $strategy;
}
// do this if you need to expose the functionality.
public function getData(){
return $this->dataStrategy->getData();
}
// or if you are just using it in your class
public function renderWidget($option){
$data = $this->dataStrategy->getData($option);
// use the data to render the widget;
return $renderedWidget;
}
}
$dataStrategy = JsonDataStrategy("http://data.source.url/jsonService.php");
$widget = new SuperWidget($dataStrategy);
Related
I wonder if it is possible to not implement a method coming from an interface and let child class do it.
For example :
abstract class Foo implements Bar
{
public abstract methodFromBar();
}
And then :
class SubFoo extends Foo
{
public methodFromBar()
{
// Implementation...
}
}
The idea behind this is to simplify development and just specifying that the subclass extends from the main class instead of writing again that the subclass implements the interface.
You don't need to mention the interface method in the parent class at all. If it doesn't implement the interfaces listed, then PHP will require that the subclass fulfills the contract instead. This will work fine:
interface Bar
{
public function methodFromBar();
}
abstract class Foo implements Bar
{
}
class SubFoo extends Foo
{
public function methodFromBar()
{
echo 'Hello world';
}
}
$subFoo = (new SubFoo)->methodFromBar();
// Hello world
See https://eval.in/1016337
If the subclass does not implement the method, you'll receive a message along the lines of
Fatal error: Class SubFoo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Bar::methodFromBar)
Whether or not you think it's a good idea for an abstract class to implement an interface is probably a discussion for another site.
So I have a question about the difference between "when we should declare normal function" and "when we should declare abstract function" in base class. Look at my example.
In the abstract class:
abstract class Birds {
abstract public function fly();
}
class Swallow extends Birds {
public function fly() {
// This function override fly function in Birds class
echo "Implement fly function in Swallow class";
}
}
In the normal class:
class Birds {
public function fly() {
echo "Implement fly function in Birds class";
}
}
class Swallow extends Birds {
public function fly() {
// This function override fly function in Birds class
echo "Implement fly function in Swallow class";
}
}
What you can see. The fly function in Swallow class is inherited by Birds class (in all cases). They are a same thing. So I'm embarrassed and I dont know when we should declare abstract function in base class?
Thanks for your help!
Abstract functions are actually only an interface. E.g. there's no difference in your example between abstract class and if it would be an interface (that's because there's only abstract method).
//abstract class
abstract class Birds {
abstract public function fly();
}
//interface
interface Birds {
public function fly();
}
That's because abstract methods have the same purpose that interface's method. When you somewhere else create a function (or method or a class or another interface etc.), and you will require any Birds instance, you will be sure you have that abstract method avaiable, although it was not implemented in Birds.
public function sendBirdToSpace(Birds $bird) { //no matter what Bird subclass
$bird->fly(); //you're sure this method is avaiable
}
Also usually you will have more than one child class. When it comes to that, it's getting more clear about abstract method.
It's actually pretty simple. Should Birds have a default behaviour implementation of flying? That's all. If every bird should can fly, but there's no default method - make it abstract.
Taken from PHP OOP Class Abstraction:
When inheriting from an abstract class, all methods marked abstract in
the parent's class declaration must be defined by the child;
additionally, these methods must be defined with the same (or a less
restricted) visibility. For example, if the abstract method is defined
as protected, the function implementation must be defined as either
protected or public, but not private.
This is essentially saying that your Swallow class has to inherit (have) the fly() method in it if it extends the Bird class based off of its abstract definition.
The general rule of thumb when harnessing abstract methods is when you want normality among classes.
Take the following for example:
Class Car {
abstract public function make();
abstract public function model();
}
This is our "base" class. Anything that extends from this has to specify the make() & model() methods.
Class Tesla extends Car {
public function make() {}
public function mmodel() {}
}
As you see above, our Tesla class has the required methods within. If you do not include these methods, you'll have PHP errors thrown.
Note
If you're exploring this option of "container" like development, then I'd suggest that you have a good look at PHP OOP Object Interfaces too, well worth it!
I'm facing the following issue in PHPStorm 9:
Say I have an interface FieldInterface that has some methods:
namespace Acme;
interface FieldInterface {
public function methodA();
public function methodB();
}
then I have an abstract class that implements base functionality of the interface. That abstract class has the user to implement certain methods, let's say it's methodB in our example:
namespace Acme;
abstract class AbstractField implements FieldInterface {
public function methodA() {
// implement methodA
}
public abstract function methodB(); // have the user implement it
}
And finally I have some ready-to-use class StringField:
namespace Acme;
class StringField extends AbstractField {
public function methodB() {
// implement methodB
}
}
At this point everything's going well. But if I add new method in the FieldInterface, PHPStorm does not say that anything is wrong with AbstractField while it's obvious that I should add public abstract function newMethod(); in there. However, it spots the error in StringField class instead.
It could be understood from the point that abstract classes are made for the purpose of extention, but usually you extend the abstract class rather than implement underlying interface. The whole meaning of making abstract class is to save user's time for implementing the interface. So why PHPStorm forces me to implement interface in concrete class rather than forcing me to implement it in abstract class that is explicitly implements the interface.
So I wonder if it is a bug in PHPStorm, or maybe it's done on purpose. Either way, is there any workaround?
That's how it should be, showing an error in the abstract class would be wrong.
In fact, public abstract function methodB(); is redundant because the abstract class already "inherits" this abstract method from the interface as it does not implement it.
The only workaround is to make AbstractField not abstract.
I have a class: site_info, which loads the site configurations parameters.
I also have a router class, a user class and a search class. The search class requires the properties and methods from the user class, router class and site_info, but at present router class extends site_info, search class extends site_info and user extends site_info.
Should I instead have site_info, user class and router all in a single class and then have search class extend this class? Or is there a better way.
Each of these classes are represented by class instances and site_info is overloaded with an array into the constructor to populate some of the class properties.
Have a look at this example no inheritance or instances whatsoever (and still able to get a private property):
Class MyClass {
private static $myProperty = "test";
public static function getProp(){
return self::$myProperty;
}
}
Class MyOtherClass {
public static function getProperty(){
return MyClass::getProp();
}
}
echo MyOtherClass::getProperty(); //Echos test
I am studying the differences between Abstract and Interface and I read some sentence
saying
A child class can only extend a single abstract (or any other) class,
whereas an interface can extend or a class can implement multiple
other interfaces.
I understand when he says, “A child class can only extend a single abstract (or any other) class,” he means:
class first
{
public function Search()
{
return 'Hellow';
}
}
abstract class first2 extends first
{
}
class second extends first2
{
}
$ob = new second();
echo $ob->Search();
However, I didn’t understand the rest of his sentence, where he says, “whereas an interface can extend or a class can implement multiple other interfaces.”
Could someone please explain his last sentence and add a code example?
Thank you all and have a nice day.
You can implement more than one interface
interface C {
public function method1();
}
interface D {
public function method2();
}
class A implements C,D {
//implement from interface C
public function method1() {
}
//implement from interface D
public function method2() {
}
}
Here you will need implement methods from interface C and D. You can also extend interfaces within interfaces, like normal classes.
interface D extends C{}
It's useful when well you need some common methods. so you write "schema" into interface what methods you are expecting from base class to be implemented.
While abstract is single extended class, you canot create instance for it, only extend. It's useful when you want have some base class with common functionality or abstract methods what should be implemented later.
More you can always read at php.net - interfaces