This comment might be particularly helpful for users
Hi, Thank you for this course. I’ve just come from the Solid course, which was another great one. I’m curious why classic or abstract inheritance isn’t being used here? I understand the principle of “Composition over Inheritance,” but in your case, where archer, fighter, and mage are all character subtypes, wouldn’t inheritance be beneficial? Could you explain when I should prefer Inheritance over Composition with real use case ? Thanks.
That is a very good question. Inheritance usually is quite handy because it's very easy to apply and override any behavior you need, but the problem is that the subclass code becomes hard to reuse and sometimes hard to maintain, it depends on how complex your class hierarchy is. In the context of the game, it's impossible to combine the behavior of characters, for example, if you want to implement a Mage-Fighter class, you just can't use inheritance because PHP does not allow multiple inheritance like C++ does. In short, favor composition over inheritance but also keep it simple. If you have a very simple hierarchy and you know that code reusability is not a problem, then go with inheritance, but as soon as you need more flexibility, refactor your code so you can "compose" your classes
This comment might be particularly helpful for users
For the purpose of "rewrite a class from outside", I often use inheritance from a abstract class. Like this:
abstract class PaymentService {
public function process($amount){
// do common thing
$this->doThePaymentStuff($amount);
// other important thing
}
abstract function doThePaymentStuff($amount);
}
class CreditCard extends PaymentService(){
public function doThePaymentStuff($amount){
// logic credit card
}
}
$creditCard = new CreditCard();
$creditCard->process($amount);
Is this same as strategy pattern? Or is this a bad pratice ? Thanks.
The strategy and template patterns solve the same problem (add behavior to an existing piece of code) but in different ways. The downside of "template" is that it uses inheritance, but it's easier to instantiate your objects. The downside of "strategy" is that it's harder to instantiate your objects, but it relies on composition, and you can change the implementation at runtime (perhaps you have a setPaymentProcessor() method)
We could get fancy by moving the part we want to reuse into a protected function so that we can call it from our sub-class... but this is getting a little ugly. Ideally we can solve problems without inheritance whenever possible.
Hello and thanks for everything. I just wanted to ask, is it ok that all the AttackTypes except the MultiAttack don't have the constructor? They all implement an interface, but only MultiAttack has a constructor which accepts an array of attack types. Shouldn't we move the constructor to the interface and make the parameter optional?
Interface AttackType
{
public function construct(private array $attackTypes = []);
public functoin performAttack(int $baseDamage): int;
}
That's a good question :) - It's not common to make the constructor part of an interface, although PHP allows it. In this case, only the MultiAttackType class needs a constructor, so we would complicate the design if we move it into the interface. Besides that, our goal is to allow "anyone" to use an AttackType, but we do not want them to actually instantiate those AttackType objects. That's why we introduced a builder and a sort of factory (CharacterBuilderFactory). You'll see those classes in the following chapters
Cheers!
Please, log in to vote for this comment
|
Share Comment
"Houston: no signs of life" Start the conversation!
8 Comments
Hi,
Thank you for this course. I’ve just come from the Solid course, which was another great one. I’m curious why classic or abstract inheritance isn’t being used here? I understand the principle of “Composition over Inheritance,” but in your case, where archer, fighter, and mage are all character subtypes, wouldn’t inheritance be beneficial? Could you explain when I should prefer Inheritance over Composition with real use case ?
Thanks.
Hey @Armel-Z
That is a very good question. Inheritance usually is quite handy because it's very easy to apply and override any behavior you need, but the problem is that the subclass code becomes hard to reuse and sometimes hard to maintain, it depends on how complex your class hierarchy is. In the context of the game, it's impossible to combine the behavior of characters, for example, if you want to implement a Mage-Fighter class, you just can't use inheritance because PHP does not allow multiple inheritance like C++ does.
In short, favor composition over inheritance but also keep it simple. If you have a very simple hierarchy and you know that code reusability is not a problem, then go with inheritance, but as soon as you need more flexibility, refactor your code so you can "compose" your classes
Cheers!
Hi @MolloKhan ,
Thank you for you reply !
For the purpose of "rewrite a class from outside", I often use inheritance from a abstract class. Like this:
Is this same as strategy pattern? Or is this a bad pratice ?
Thanks.
Hey Dang!
That's a good question. You may have already known this, but you're using a different pattern in your example, the "Template method" pattern. More info here https://refactoring.guru/design-patterns/template-method
The strategy and template patterns solve the same problem (add behavior to an existing piece of code) but in different ways. The downside of "template" is that it uses inheritance, but it's easier to instantiate your objects.
The downside of "strategy" is that it's harder to instantiate your objects, but it relies on composition, and you can change the implementation at runtime (perhaps you have a
setPaymentProcessor()method)Cheers!
Im no expert, but this is a literal quotation:
Hello and thanks for everything.
I just wanted to ask, is it ok that all the AttackTypes except the MultiAttack don't have the constructor?
They all implement an interface, but only MultiAttack has a constructor which accepts an array of attack types.
Shouldn't we move the constructor to the interface and make the parameter optional?
sth like this?
Hey Alireza,
That's a good question :) - It's not common to make the constructor part of an interface, although PHP allows it. In this case, only the
MultiAttackTypeclass needs a constructor, so we would complicate the design if we move it into the interface. Besides that, our goal is to allow "anyone" to use anAttackType, but we do not want them to actually instantiate thoseAttackTypeobjects. That's why we introduced a builder and a sort of factory (CharacterBuilderFactory). You'll see those classes in the following chaptersCheers!
"Houston: no signs of life"
Start the conversation!