Reputation: 1097
While working on a project i stumbled across a question relating to the proper way of choosing the correct form of code reuse in terms of traits vs. abstract base classes. I came across the point where i have multiple abstract base classes but can only inherit from one due multiple inheritance restrictions from PHP. Rethinking this makes me questioning my design and so i want to know how others would solve this problem.
Following scenario
In my project i have two kind of calculations
Setting up the interfaces
interface SimpleResultInterface{
public function getValue();
}
interface GroupedResultInterface extends SimpleResultInterface {
public function getGroupValues();
}
Setting up the base classes
Avoiding code duplication as a good form of design i set up two abstract base classes.
abstract class SimpleResultBase implements SimpleResultInterface{
public function getValue(){
return 1;
}
}
abstract class GroupedResultBase extends SimpleResultBase implements GroupedResultInterface {
public function getGroupValues(){
return array(
"group1" => 1,
"group2" => 2,
"group3" => 3,
);
}
}
So the first question here is
I have chosen yes because otherwise i would have to duplicate the getValue method from SimpleResultBase
What we have so far
Now i can epxpress
Going concrete where the troubles start
At this point there are no concrete classes. Now i want to make two concrete classes which have a relationship together respecting the interface definitons.
class OEESimpleResult extends SimpleResultBase {
}
class OEEGroupedResult extends GroupedResultBase{
}
this works very nicely but what i can't do is this
class OEESimpleResult extends SimpleResultBase {
}
class OEEGroupedResult extends OEESimpleResult,GroupedResultBase {
}
interface GroupedResultInterface extends SimpleResultInterface
As above noted in the interface definiton. Each grouped result is also a simple result. So i would have expected that OEEGroupedResult also is a OEESimpleResult
But when i would do this i can not reuse my abstract base class GroupedResultBase because multiple inheritance is not allowed. This leads me to following questions.
Thank u for your help :)
Upvotes: 3
Views: 1825
Reputation: 405
As you are working in oop style, you might hear about SOLID principles. So your design breaks the following letters S,I,D with potential to break O and L.
So how do you broke "S": Right here!
class OEEGroupedResult extends OEESimpleResult,GroupedResultBase {
}
Suddenly or luckily php doesn't allow it, but your class would provide some additional separate logic, so you will have at least two reasons to change it. But yeah, it's because of
interface GroupedResultInterface extends SimpleResultInterface {
public function getGroupValues();
}
Here's your I letter breaks. Solution is pretty simple: think about methods your GroupedResultInterface really needs and put it inside and really means that these methods must do the same job. They are not as you are breaking letter D here:
abstract class SimpleResultBase implements SimpleResultInterface{
public function getValue(){
return 1;
}
}
abstract class GroupedResultBase extends SimpleResultBase implements GroupedResultInterface {
public function getGroupValues(){
return array(
"group1" => 1,
"group2" => 2,
"group3" => 3,
);
}
}
Your class class GroupedResultBase
depends on concrete method of another class. But you will quickly fix it after interface segregation.
Notice. I'm using traits when I can't change something inside vendor classes. Only. It's just me, but when I think that trait will help me then something is wrong with architecture. It's up to you of course.
Little link: https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Have fun!
Upvotes: 2