I'm working with a framework, but for sometimes I need to alter some methods by overloading classes.
My problem is when a class B inherits from a class A and where I need to overload them both, eg:
class B extends A {}
First I overload A and B, in order to alter some of their methods:
class AA extends A {}
class BB extends B {}
But then what to do for BB extends from AA
In others words ('<--' means extends):
class B <--- class A
^ ^
| |
| |
class BB <-?- class AA
i think you might be looking for Composition
Yes. This is where Traits or Composition comes to play.
Basically, traits in programming concept is a group of functionality that you can include into any class. Think of traits as just a set of functions you can add to your classes.
What you want to accomplish is called multiple inheritance, but that is not supported by PHP and most other recent languages. There is rarely a good reason to use multiple inheritance, and since it can be confusing, it is generally frowned upon.
As mentioned, you can probably achieve what you want in à clean wat through composition, but without more information about your classes, it is impossible to give Amy specific advice.
A good rule of thumb is always prefer composition over inheritance. Once you start thinking that way and almost always using composition, the decision when to use inheritance becomes pretty obvious.
Related
I have a design problem where my classes are set up in such a way:
abstract class Advertiser abstract class AdvertiserCampaign
| |
| |
class AdvUno extends Advertiser class AdvUnoCampaign extends AdvertiserCampaign
class AdvDos extends Advertiser class AdvDosCampaign extends AdvertiserCampaign
class AdvTre extends Advertiser class AdvTreCampaign extends AdvertiserCampaign
The problem is that AdvUno and AdvUnoCampaign both need a special authentication method that's not necessary for the others. Right now I've placed it in AdvUno, but again, it'll be needed by AdvUnoCampaign (and a bunch of other classes that are set up in this way).
I can't make AdvUnoCampaign extend AdvUno since there's no multiple inheritance in PHP, but also because it's just generally not a good, clean design practice.
If I make AdvertiserCampaign extend Advertiser, then all of the extending classes below (AdvUnoCampaign, AdvDosCampaign, etc) must implement a bunch of abstract methods that are of no concern to them, and which are already implemented in each of the Advertiser classes.
In short, what's the best design practice in this sort of situation? I'd rather not just copy and paste the code into all of the AdvOne classes. Any help or advice would be appreciated. Thanks!
Parallel Inheritance Hierarchies are considered a code smell, something that should be refactored.
Martin Fowler suggests in "Refactoring":
The general strategy for eliminating the duplication is to make sure that instances of one
hierarchy refer to instances of the other. If you use Move Method and Move Field, the hierarchy
on the referring class disappears.
But I think you can go one step further. I don't know, what your decision was based on to make sub classes for each advertiser and their campaigns, but I would challenge this decision. A good practise to follow is to Favor Composition over Inheritance.
You could start like that:
class Advertiser
{
protected $authentication;
}
class AdvertiserCampaign
{
protected $authentication;
}
interface AdvertiserAuthentication
{
}
class SpecialAuthenticationForAdvertiserUno implements AdvertiserAuthentication
{
}
class NoSpecialAuthenticationForOtherAdvertisers implements AdvertiserAuthentication
{
}
Now the first difference between the advertisers is moved into another class. Go on with other differences until each advertiser is just an object of Advertiser composed in a different way. The same goes for the campaigns. I would like to be more concrete but as stated before, I have no idea why your advertisers all have their own classes in the first place.
In general, to resolve problems similar to yours the Bridge design pattern is commonly used.
http://sourcemaking.com/design_patterns/bridge
There are classes A and B both extend class C and there are some common methods in class C that are needed for both class A and B.
There are cases that it needs to invoke the method in class B from class A, which is at the moment achieved by creating an object of class B in class A. But, more and more methods are added into class C, so it is inefficient to create an object of class B inside class A due to the duplication.
My question's that what are the possible solutions to refactoring the classes so that they have better structure, e.g using object oriented, factory pattern, etc.?
Thanks in advance.
You could use Traits (only PHP >= 5.4.0).
If the methods needed by A and B can be factored out into a single responsibility then you might consider adding class D which is then used by class A and B. The Single Responsibility Principal (SRP) is the S in SOLID, which are guidelines for object oriented design.
You can find plenty of information about SOLID in general, and the application of SRP in PHP on Google. I gave a presentation to our local PHP Meetup Group on SRP which can be found online here: SRP Presentation
I have been trying to learn OOP using PHP5 and I am having trouble wrapping my head around a couple of things.
First; I am understanding Inheritance in OOP, but what I am not understanding in PHP is why I can only use extends once to extend a parent class. I have been doing some reading online and a few times I have seen where it is not good practice to use extends more than once, that's why it's not available, is this true?
Second; Abstract vs. Interface, I read a way to Inherit one class many times is to use Interface and or Abstract. Is this correct?
Third; I am writing a very simple class using Inheritance and I am having a problem understanding how to properly contruct it. I have looked thru php.net and OS and have seen many classes and how they are written, but could anyone take the time to write a simple example in PHP using .... let's say a mammal class as the parent class and have dog, cat, and bear and the child classes.
I know I could find something online that has already been written, but this way I can converse with the person who wrote the class.
First; I am understanding Inheritance in OOP, but what I am not understanding in PHP is why I can only use extends once to extend a parent class. I have been doing some reading online and a few times I have seen where it is not good practice to use extends more than once, that's why it's not available, is this true?
In short: Its just a design decission from the PHP core developers. Multiple inheritance brings up many questions, for example what should happen, when two parent classes implements the same method? To avoid such conflicts some languages decide to not support it (e.g. Java too ;)). There is no real downside in it.
Second; Abstract vs. Interface, I read a way to Inherit one class many times is to use Interface and or Abstract. Is this correct?
You can extend every class as much as you like. There is no limitation neither for classes, abstract classes, nor interfaces. However, its possible to implement (implements keyword) more than one interface into one class.
Third; I am writing a very simple class using Inheritance and I am having a problem understanding how to properly contruct it. I have looked thru php.net and OS and have seen many classes and how they are written, but could anyone take the time to write a simple example in PHP using .... let's say a mammal class as the parent class and have dog, cat, and bear and the child classes.
abstract class Mammal {}
class Dog extends Mammal {}
class Cat extends Mammal {}
class Bear extends Mammal {}
Yes it's true PHP only officialy supports extending one class at a time, its a bug bear to all OOP because there's no good OOP reason not to be able to but there is for the language. It's also true you can circumvent it, not recommended however because it's not supported by the language for a reason (I forget now).
Not sure what you mean by versus, Abstract classes are classes that should be abstracted before using them. Think of them as 80% complete classes, there are a few functions missing for it to work which must be implemented on a per application level.
Interfaces are the kind of bones of a class, there's no functionality there but all functions are defined. They aren't to be extended or used they are to be referenced against.If a class implements and interface it commits to implement all the function stated in the interfaces (and possibly more) and PHP throws an error if that's not the case.
A very simple example
class Mammal{
function getBones(){}
}
class Dog extends Mammal{
function bark(){}
}
class Cat extends Mammal{
function meow(){}
}
$d = new Dog()
$d->bark()
//Works
$d->getBones()
//works
$d->meow()
//does not work, is a cat function
I think you are talking about Multiple Inheritance? Technically, it's a design decision of the PHP developers. There are other languages which allow it.
Multiple inheritance has some technical problems (Diamond Problem), but there is a good theoretical argument against it: A class should have one responsibility (Single Responsibility Principle, it talks of "object" because there are classless yet object-oriented languages). Two different classes usually have different responsibilities, so if a class inherits from both of them, it would have two responsibilities, violating the SRP.
See Search for "abstract class interface" – use interface to define the methods a class must implement to satisfy a contract, use abstract class if you want to partially implement something (usually an interface).
Impossible, because you did not say which aspects of the mammals should be modeled. Without knowing that, it would even be impossible to know if different mammal classes or a common base class are needed.
I've faced a situation when I want to extend two parent classes, but php does not allow this.
Why I can't extend more than one class, but can implement more than one interface. What's wrong with extending many classes?
It seemed to me like a pretty obvious thing, until I got parse errors.
Is it a bad practice? If so, what are the alternatives?
Is it possible in other languages?
Why multiple inheritance is forbidden in some/most programming languages is argued with the diamond problem http://en.wikipedia.org/wiki/Diamond_problem.
Put simple if you have a car that can swim and drive because it inherits from vehicle and boat what happens on execution of the move function!?
Try using interfaces and follow the Strategy pattern or State pattern.
You're probably looking for: Multiple Inheritance in PHP.
It seems to be possible in Python.
Take a look at Can I extend a class using more than 1 class in PHP?
Is it a bad practice? If so, what are alternatives?
Unless the language is specifically designed for it, yes. Consider, you have two classes, A and B. Both classes provide a public method foo() which have identical signatures (not hard in PHP). Now, you make a class C which extends both A and B.
Now, you call C.foo(). Without explicit instructions, how does the interpreter know which version of foo() to call?
It's not supported by PHP. It can however be simulated using runkit, APD or by just overriding __call and __get to simulate inheritance from multiple classes. Symfony (and I seldomly recommand that) also provides "sfMixin" or "sfMixer" for multiple inheritance.
Separate classes implementing the same method is not a good argument against multiple inheritance, as currently multiple interfaces can be implemented. You just can't implement two interfaces with the same method. Quote from http://www.php.net/manual/en/language.oop5.interfaces.php: "A class cannot implement two interfaces that share function names, since it would cause ambiguity."
I know this question is 2 years old but I've only just had the same problem. My work-around is this: if you have one regular class and two abstracts and want to extend both, e.g abstract class AbstractOne and abstract class AbstractTwo, you can say:
abstract class AbstractOne extends AbstractTwo {
}
Then add to the main class like this:
class MyMainClass extends AbstractOne {
}
This way, it inherits both AbstractOne and AbstractTwo.
From a quick Google search and a the wikipedia article on Multiple Inheritance, which quotes:
Multiple inheritance refers to a feature of some object-oriented programming languages in which a class can inherit behaviors and features from more than one superclass. This contrasts with single inheritance, where a class may inherit from at most one superclass.
I understand that PHP doesn't allow multiple inheritance. What I can't find a clear answer on, however, is whether it allows more than one class to extend a superclass. Example:
class a {}
class b extends a {}
class c extends a {}
In terms of what I'm trying to do, I'm making an RPG and want a 'generic' character class to include all the methods and properties that make the template of a character. Then I want classes to include specifics for each type of character (warrior, mage, etc), such as stats modifiers and special attacks.
Is this possible?
Yes, it's perfectly possible. The entire purpose of inheritance is that multiple children can inherit common functionality from a parent.
Yes, multiple classes can extend the same class, per your code example.
This is the foundation of OOP. It's possible.
Yes, any class can extend a base class. In your example, it just isn't possible for class c to extend both a and b.
So in an adjusted example like the one above
class a {}
class b extends a {}
class c extends b {}
c could not get to properties of a ?