Abstract Class X Interface
You started by creating the Pet
class with common properties between derived classes. Is there any reason not to continue doing this for methods and events? Passing these common members to Pet
already greatly simplifies. Renan suggested putting everything together in an interface called Pet
. But you already have this interface. An abstract class is both a class and an interface. The abstract class Pet
is its interface.
Generalize what you can
Follow Renan's recommendation and turn Pets' sound emission methods into something generic. Remember that sound emission is the only action, the way the sounds are emitted is that it will vary, meaning the implementation varies. What you did was exactly what is described in the link provided by Joshua Edward.
You probably still do not quite understand the concept of what the interface is. It states actions and not the mechanism (usually, but we are not going to make the mechanism being used in other ways, not every language does this), the implementation of these actions. Understand that abstract class interfaces and methods define behavior, but do not implement this behavior. Only concrete classes can implement behaviors. When you treat a barking or neighing without the abstraction of the animals' ability to emit sounds, you are leaving aside one of the advantages of object orientation which is the actual abstraction (having a bark abstraction to implement a bark is an artificial abstraction).
Maybe all of these sound emissions are already covered in the Talk()
method and only the different implementations are required. At this point I disagree with Renan that each type of Pet
does not need specific classes. You need to be able to do the specific implementations in these classes. The suggested solution would only work if all sound emissions were equal.
If Talk()
is for something else, you can create another generic method to denote the sounding action of pets, Speak()
maybe?.
When you do this, all interfaces, individually, will be implemented only in one class each. Can you tell why this is necessary? If you have a good reason, okay, if you do not have it, do not. In general an interface is only interesting when it is used in at least two classes. Future use is not a good reason. If in the future you need, then you create the interfaces. There is no problem in creating an interface and putting it in an existing class as long as the class design is right. An existing class can take on a new interface if it already has the desired behavior. This does not hurt any principle and does not create problems.
I say more. If you can abstract the method pairs (do not force the slash, just do it if you do the best), Eat
and Recharge
, Sleep
and Maintenance
, Poop
, OilLeak
, you might find out are the same action with different implementations.
Future implementation
If you ever need a HybridPet
that implements some methods (and events obviously) unique to AnimalPet
and also some methods unique to RoboticPet
, then you create IAnimalPet
which will be used in class AnimalPet
and HybridPet
and IRoboticPet
that will be used in RoboticPet
and HybridPet
. This if they really do help. You will only need two interfaces.
Conclusion
Notice that you need zero interfaces? In your case, you have many interfaces . In the current modeling, an interface is very.
Do not forget that in abstract classes, unlike interfaces you can give a default implementation in the methods if they match for some types of pets.
Do not worry about the future in this case. If you have trouble creating a consistent interface in the future it's because your model was wrong, not because you stopped creating the interface before.
I find your case very simple and do not need to make the hassle of making a specialization an exception (and probably generating an exception in runtime in this case) as suggested by Renan.
If you improve modeling and still have questions post new question to continue helping with the new problem.