What are the consequences of implementing the same interface through two different routes in PHP, are there any?
What I mean, is something like this:
interface baseInterface {}
abstract class baseClass implements baseInterface { }
interface myInterface extends baseInterface {}
class myClass extends baseClass implements myInterface {}
In this case myClass implements baseInterface from two different parents - myInterface and baseClass. Are there any consequences to this? My instinct is that PHP should handle this fine, but I just want to make sure. What exactly does PHP do in this case? Does it just check to see that the necessary functions are implemented for the interface each time it discovers it and call it a day or does it do something more?
That will all work fine. You'll still have to keep them all straight in your head and documentation though :)
In other words, there are no technical concerns.
Related
After reading http://php.net/manual/en/language.oop5.interfaces.php, I am uncertain when I should extend interfaces or use multiple interfaces or extend classes with interfaces. What criteria does one use to determine which approach to take?
<?php
interface Interface_A
{
public function aaa();
}
interface Interface_B
{
public function bbb();
}
interface Interface_C extends Interface_A
{
public function bbb();
}
class Class_A implements Interface_A, Interface_B
{
public function aaa(){}
public function bbb(){}
}
class Class_B implements Interface_C
{
public function aaa(){}
public function bbb(){}
}
class Class_C implements Interface_A
{
public function aaa(){}
}
class Class_D extends Class_C implements Interface_B
{
//public function aaa(){} //Use parent
public function bbb(){}
}
The one good approach, I think, is to follow Composition over inheritance and Interface segregation principle by default. This automatically will rule out "extend interfaces" and "extend classes with interfaces" for most cases. For the remaining cases, as always, it depends.
Interfaces are contracts, so when a class implements interfaces it shows other classes that it has appropriate methods. This provides the base for Liskov substitution principle.
From your examples:
If some of your classes rely on aaa() method and some of your classes rely on both aaa() and bbb() methods, and none rely on bbb() alone, then, you, in fact, can extend Interface_A and thus add the method to it.
If all previous keeps but some of the classes also rely on bbb() alone, then it is better to have Interface_A and Interface_B. And if you want to enforce both those methods with one interface you can create combined one:
interface Interface_C extends Interface_A, Interface_B
{
}
This is my subjective opinion but extending classes and also implementing the interface is a bit complex from the understanding point of view and not really useful (or I'd rather say not really practical). In general, you implement an interface, so that you can type hint it. If you type hint Interface_B and your Class_D implements it, then you should not care if this class implements any other interfaces. This means, that you can have Class_C as a dependency for Class_D, and simply can avoid using inheritance at all.
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 am trying to work out the best way to design my classes and I think abstract classes it the right way here, but I'm not sure! I am building a plugin for Wordpress carts that at the moment, will work for both Woocommerce and WP-Ecommerce. As these two systems have different implementations of certain functionality, such as getting an order object, I want to create a separate class for each platform.
I have the following which will contain generic methods that should be available to the classes that inherit from it. This class should never be instantiated:
class Order_Export {
}
I then have 2 more classes that will inherit from the above:
class Order_WooExport extends Order_Export {
}
class Order_WPExport extends Order_Export{
}
Is my design right here? Am I right in saying the class Order_Export should be an abstract class? What about methods that I want the class inheriting to implement? Do I simply mark the signature in the abstract class and not provide a body, or do interfaces come into play somewhere here?
How about instantiating the right class? Do I create a factory that will return one or the other?
Any advice appreciated!
That sound correct to use abstract base class, as long as you are sure to never need to instantiate Order_Export :
abstract class Order_Export
{
abstract protected function someMeth1();
abstract protected function someMeth2();
public function someMeth3() {
// Do common thing to both Order_WooExport and Order_WPExport
// using someMeth1(), someMeth2()...
}
}
Then :
class Order_WooExport extends Order_Export
{
protected function someMeth1() {
// Do something specific
}
protected function someMeth2() {
// Do something specific
}
}
Finally, the factory seems to be the right way to go too.
I haven't used abstract classes much in practice, though I understand what they are : a way to dictate to subclasses which methods must be implemented.
I just put a Kohana project through Doxygen and can see the class hierarchy in its entirety. I see that, at the top of the chain we have a factory:
abstract class Kohana_Model {
public static function factory($name){
// Add the model prefix
$class = 'Model_'.$name;
return new $class;
}
}
Inherited directly below that, we have an empty abstract class:
abstract class Model extends Kohana_Model {}
... And below that, there are three inherited classes: Kohana_Model_Database, Kohana_ORM, and Model_Foobar.
Would someone please explain the programming reasoning for this - what is the purpose of having an empty abstract class this high up in the chain? (and, at all?)
Why not have Kohana_Model_Database, Kohana_ORM, and Model_Foobar inherit directly from Kohana_Model, when there is (apparently?) no other branching or inheritance going on between Model and Kohana_Model?
Answers you're seeking for are Cascading File System and Transparent Extensions.
It allows you to create a model by calling
class News_Model extends Model
by default, and that will automatically then extend Kohana_Model and things will be hunky dory.
It also lets you extend Kohana_Model by creating your own Model file
class Model extends Kohana_Model
which overrides the abstract Model class, and allows you to add custom functionality. Then, when you upgrade your Kohana version to (say) 3.4, your extended Model doesn't get overwritten by the new Kohana files.
I have something like :
interface IProduct { }
class Product implements IProduct { }
class SpecificProduct extends Product { }
I need to have a interface, that extends IProduct, for my SpecificProduct.
Can I just do something like :
interface ISpecificProduct { }
class SpecificProduct extends Product implements ISpecificProduct { }
or will it overwrite the IProduct interface ?
This works in PHP, this way, just go through:
class SpecificProduct as it extends Product it implements IProduct already. As it implements ISpecificProduct as well, it has both interfaces.
SpecificProduct now has two interfaces then:
IProduct
ISpecificProduct
Yes, you can do that, and no, it will not "overwrite" IProduct, it adds to it.
In case you are using the ISpecificProduct interface somewhere and would like to know about the methods in IProduct, ISpecificProduct can also extend IProduct:
interface ISpecificProduct extends IProduct
In this case, SpecificProduct gains knowledge of the method signatures from IProduct in two ways.
See PHP documentation on interfaces for more information.
As a side note, if you have a matching interface for every concrete class, there is probably something inefficient or unnecessary going on in your object design.