Real Life example of Polymorphism from Class Room - oop

Once my teacher asked me to give example of polymorphism from class room.
I told him that you are best example of polymorphism. As in college you are a teacher and in home you are husband or father. So your are one method but in different states you are behaving accordingly. And also you are extending human so you can be treated polymorphically as human.
(Considering in mind definition of polymorphism: Acquiring more than one form)
Can it be consider as good example of polymorphism ?
Thanks.

In your example, you give different behaviours for different states.
In OOP this is expressed through interfaces.
So, it would be modelled something like this:
class Human
{
Date Birthdate;
}
interface ITeacher
{
void Teach();
}
interface IHusband
{
void Pray();
}
interface IFather
{
void Love(); // methods in IFather and IHusband can be interchanged
}
class Person extends Human implements ITeacher, IHusband, IFather
{
// implementations inserted here
}
Now you can use those behaviours and the fact that he is a human in different cases.
Like:
Human yourTeacher = new Human("1970/05/01");
Class class = new Class();
class.Teachers.Add(yourTeacher); // expecting that it is a collection of ITeachers.
Pub pub = new Pub();
pub.DrunkPeople.Add(yourTeacher); // accepting only humans older than 21 here
So, polymorphism is about ONE object that behaves different in different cases... and inheritance.

Related

General code design: shared and alternating patterns

The situation
My question applies to all programming languages with classes and inheritance. Im sure the answer is out there somewhere already, but I could not find it as i don’t have the right terminology to use.
Lets take the classic example. We got Dogs and Cats which are both of the type Animal:
abstract class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
Simple enough. Some behavior is shared in the Animal class, anything that differs between Cat and Dog is coded in their respective classes.
Now suppose we got 2 planets. Earth and Mars. Both planets have Cats and Dogs. But, behavior for all animals on Earth differs from all animals on Mars. They, for example, experience a difference in gravity which affects the way they move.
There is no difference between specific animal types between the planets. Thus, all differences between animals on Earth and Mars can be coded at the parent level, that of the Animal class.
Not only that, but some behavior is available for all Animal instances on Mars that does not exist on Earth.
Ideally, in code dealing with these animals, we deal with a MarsAnimal or EarthAnimal class that is implemented by either a Dog or Cat. The implementing code does not need to know if they are Dogs or Cats. It does already know on what planet the Animal lives though.
What I thought about already
One solution would be the following:
abstract class Animal {
}
abstract class Cat extends Animal {
}
abstract class Dog extends Animal {
}
interface MarsAnimal {
}
interface EarthAnimal {
}
class MarsCat extends Cat implements MarsAnimal {
}
class MarsDog extends Dog implements MarsAnimal {
}
class EarthCat extends Cat implements EarthAnimal {
}
class EarthDog extends Dog implements EarthAnimal {
}
Ofc, the obvious problem with this is, that any behavior specific to MarsAnimal would need to be implemented in both the MarsCat and MarsDog classes. That’s ugly code duplication and definitely not what I was looking for.
The only semi-acceptable method I could think of was the following:
abstract class Animal {
private PlanetAnimal planetAnimal;
public function myBehavior() {
this.planetAnimal.myBehavior();
}
}
class Cat extends Animal {
}
class Dog extends Animal {
}
interface PlanetAnimal {
function myBehavior();
}
class MarsAnimal implements PlanetAnimal {
public function myBehavior() {
// marsAnimal- specific behavior here
}
}
class EarthAnimal implements PlanetAnimal {
public function myBehavior() {
// earthAnimal- specific behavior here
}
}
Thus, when creating a Cat or Dog instance, since we know what planet they are from at that point in the code, we give them the needed PlanetAnimal instance in their constructor (either MarsAnimal or EarthAnimal).
This is close. The only problem with this is, like I said, some behavior exists only for all animals on Mars. I’d have to still implement a method in both the Animal and PlanetAnimal classes that is used only for Mars. If this is the only solution then sure, but it feels like there should be some better method out there.
So, any ideas? I’d love to hear!
Edit 1
Based on questions, a small clarification: the main problem here is how to implement shared behavior between many different categories. There is shared behavior:
between all animals on all planets;
between all animals on a specific planet;
between all animals of a specific type (i.e. Cat or Dog), irrespective of what planet they are on
Edit 2
I work mainly in Java and PHP. This question specifically was asked after I encountered this in PHP, though I know I had similar situations in Java too. I know, for PHP, my first proposed solution could work in combination with Traits. That might even be where I end up. But, everywhere online I saw people warning against the use of Traits, saying it is almost always/ always bad code design. That's why I'm searching for the best solution
The solution you are looking for is a design pattern called the Strategy pattern. The pattern is defined as follows:
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
In your case, the Animal class would be the context, and the PlanetAnimal class would be the strategy. The context would be responsible for delegating to the correct strategy for each concrete implementation. In your example, the context would be the Animal class, and the strategy would be the PlanetAnimal class. The context would be responsible for delegating to the correct strategy for each concrete implementation.
Something like this, in Python:
class Animal:
def __init__(self, animalStrategy):
self.animalStrategy = animalStrategy
def walking(self):
raise NotImplementedError()
class Cat(Animal):
def walking(self):
return self.animalStrategy.walking(canJump=True, canFly=False, canSwim=False, speed=10)
class Bird(Animal):
def walking(self):
return self.animalStrategy.walking(canJump=True, canFly=True, canSwim=False, speed=20, walkSpeed=2)
class MarsAnimalStrategy:
def walking(self, canJump, canFly, canSwim, speed):
return f"walking on Mars with speed {speed}"
class EarthAnimalStrategy:
def walking(self, canJump, canFly, canSwim, speed, walkSpeed):
return f"walking on Earth with speed {speed} and walkSpeed {walkSpeed}"
marsCat = Cat(MarsAnimalStrategy())
marsCat.walking()
earthCat = Cat(EarthAnimalStrategy())
earthCat.walking()
In this way, the Animal class is not responsible for knowing how to walk on Mars or Earth, but instead delegates that responsibility to the strategy. The strategy is responsible for knowing how to walk on Mars or Earth. The context/"user" is responsible for delegating to the correct strategy for each concrete instance.
I wouldn't go into details, but consider using a composition of objects instead of class inheritance. In short, each descendant class of Animal would have to be fully tested, including an internal behavior of a parent class, and Animal could easily become a God Object, which is not a good thing. Alternatively:
class IAnimal: # Python have only classes, but consider it as an interface
def walking(self):
raise NotImplementedError()
def eating(self):
raise NotImplementedError()
# etc.
class Cat(IAnimal):
def __init__(self, physicalBody, livingEntity):
self.physicalBody = physicalBody
self.livingEntity = livingEntity
def walking(self):
direction = self.livingEntity.goalDirection()
if self.physicalBody.canMove(direction):
self.physicalBody.move(direction)
return self.livingEntity.movedTo(self.physicalBody.position)
return self.livingEntity.wasFrustrated()
Now Cat is responsible only for its own behavior, and PhysicalBody and LivingEntity are responsible for their own behavior. This way, you can easily test each class separately, and you can easily replace PhysicalBody and LivingEntity with other implementations, without changing Cat class. I would repeat, that now Cat class is highly focused solely on its own behavior and implementation of IAnimal interface/contract. Now, of course, you need to type self.physicalBody.canMove(direction) instead of self.canMove(direction), but it's a small price to pay for a better design. Differences in the behavior of Earth and Mars animals would now be represented by different implementations of LivingEntity classes, that could share some common parts.

How to deal with "optional interfaces"?

"Optional interface" is probably not a standard term, so let me give an example. Suppose I have:
interface Car {
start();
honk();
}
Now I can have like HondaCar, PriusCar, etc., implementations. Yay! But what if honking is not all that important to me or my users, so I decide to do something like this:
interface Car {
start();
canHonk(); // return true if honking is supported
honk(); // undefined behavior of canHonk is false
}
So this is what I'm calling an "optional interface", because actually supporting honk is optional. It still seems like a fine, well-defined interface, but another way you could've expressed this is by separating this into two interfaces:
interface Car {
start();
}
interface Honkable {
honk();
}
Now, if user code really needs to do some honking, you must pass it a Honkable. If it's optional, it can take a null pointer. And if it doesn't care about honking at all, it can ignore Honkable completely. However, this does put more onus on the user code to manage all this.
So, I've listed some pros and cons that I see, but I'm curious what others think. Which is the preferable pattern in which situations?
Composition over Inheritance, our subject here, is an important OOP principle. It tells us to define our objects by their functions. Which means, your second approach is the best practice. Do it like:
public class SomeCar: ICar, IHonk {}
public Interface ICar {}
public Interface IHonk {}
Design for capability instead of identity.
Two separate interfaces is the way to go in my opinion
If you want to honk, implement the interface
As others have mentioned, separate interfaces are a better solution here. It is also worth noting that it conforms to the Interface Segregation Principle from SOLID.
However, another approach would be to use a feature container:
public class FeatureContainer {
// ...
public bool isAvailable<T>() {
// ...
}
public T getFeatureOrNull<T>() {
// ...
}
}
and then have for example:
public abstract class Car : FeatureContainer {
// ...
};
public class SomeCar : Car {
public SomeCar()
: base(/* instantiate all implementations of supported interfaces */)
{}
}
so then you could have:
Car aCar = getSomeCar();
if (aCar.isAvailable<Honkable>()) {
Honkable h = aCar.getFeatureOrNull<Honkable>();
h.honk();
}
This can have of course numerous syntactical variations depending on language and desired semantics.

Object oriented design principle Abstraction

While reading about abstraction, I came across the following statement
"Abstraction captures only those details about an object that are relevant to the current perspective"
For eg.
From the driver's perspective, Car class would be
public class Car
{
void start();
void applybrakes();
void changegear();
void stop();
}
From the mechanic's perspective, Car class would be
public class Car
{
void changeOil();
void adjustBrakes();
}
My question,
While designing a system, do we design for one user perspective(either driver or mechanic) or can
we design for multiple user perspective and further abstract out based on user type?
Hope my question is clear.
Thanks
Depending on your use case you might need to deign for multiple users. In your example, if your car will be used by both the mechanic and the driver, then you cannot just ignore one set of users. In that case, you can still abstract details by using Interfaces.
You could design your object like this:
interface IDrivable {
void start();
void applyBrakes();
void changeGear();
void stop();
}
interface IFixable {
void changeOil();
void adjustBrakes();
}
public class Car : IDrivable, IFixable {
// implement all the methods here
}
Now, when a mechanic wants the car, you don't give him a Car object, instead give him an IFixable object. Similarly, the driver gets an IDrivable object. This keeps the relevant abstraction for both sets of users simultaneously.
class Driver {
private IDrivable car;
public Driver(IDrivable car) {
this.car = car;
}
public driveCar() {
this.car.start();
this.car.accelerate();
//this is invalid because a driver should not be able to do this
this.car.changeOil();
}
}
Similary, a mechanic won't have access to the methods in the interface IDrivable.
You can read more about interfaces here. Even though this is the MSDN link and uses C#, all major languages support interfaces.
I think you may be inferring too much from "perspective." I wouldn't take perspective here to mean a person or user so much as a vantage point. The idea of a view here is maybe not even a good metaphor. What we're really talking about here is division of responsibility between the smaller objects that we use to compose the larger objects.
The whole point of this idea is decoupling and modularity. You want objects that you can pull out and replace without changing everything around them. So you want your objects to be coherent, for their methods and variables to be closely related.
You might be able to get some mileage from the user metaphor in terms of the interface-client relationship between objects.

Multiple Inheritance: What's a good example?

I'm trying to find a good example for the use of multiple inheritance what cannot be done with normal interfaces.
I think it's pretty hard to find such an example which cannot be modeled in another way.
Edit: I mean, can someone name me a good real-world example of when you NEED to use multiple inheritance to implement this example as clean as possible. And it should not make use of multiple interfaces, just the way you can inherit multiple classes in C++.
The following is a classic:
class Animal {
public:
virtual void eat();
};
class Mammal : public Animal {
public:
virtual void breathe();
};
class WingedAnimal : public Animal {
public:
virtual void flap();
};
// A bat is a winged mammal
class Bat : public Mammal, public WingedAnimal {
};
Source: wiki.
One example where multiple class inheritance makes sense is the Observer pattern. This pattern describes two actors, the observer and the observable, and the former wants to be notified when the latter changes its object state.
A simplified version for notifying clients can look like this in C#:
public abstract class Observable
{
private readonly List<IObserver> _observers = new List<IObserver>();
// Objects that want to be notified when something changes in
// the observable can call this method
public void Subscribe(IObserver observer)
{
_observers.Add(observer);
}
// Subclasses can call this method when something changes
// to notify all observers
protected void Notify()
{
foreach (var observer in _observers)
observer.Notify();
}
}
This basically is the core logic you need to notify all the registered observers. You could make any class observable by deriving from this class, but as C# does only support single class inheritance, you are limited to not derive from another class. Something like this wouldn't work:
public class ImportantBaseClass { /* Members */ }
public class MyObservableSubclass : ImportantBaseClass, Observable { /* Members */ }
In these cases you often have to replicate the code that makes subclasses observable in all of them, basically violating the Don't Repeat Yourself and the Single Point of Truth principles (if you did MVVM in C#, think about it: how often did you implement the INotifyPropertyChanged interface?). A solution with multiple class inheritance would be much cleaner in my opinion. In C++, the above example would compile just fine.
Uncle Bob wrote an interesting article about this, that is where I got the example from. But this problem often applies to all interfaces that are *able (e.g. comparable, equatable, enumerable, etc.): a multiple class inheritance version is often cleaner in these cases, as stated by Bertrand Meyer in his book "Object-Oriented Software Construction".

Bridge Pattern - Composition or Aggregation?

I'm reading some books about Design Patterns and while some describe the relation between the abstraction and the implementation as a composition, some describe it as an aggregation. Now I wonder: is this dependant on the implementation? On the language? Or context?
The terms "composition" and "aggregation" mean more or less the same thing and may be used interchangeably. Aggregation may be used more frequently when describing container classes such as lists, dynamic arrays, maps, and queues where the elements are all of the same type; however, both terms may be found to describe classes defined in terms of other classes, regardless of whether those types are homogenous (all of the same type) or heterogenous (objects of different types).
To make this clearer:
class Car {
// ...
private:
Engine engine;
Hood hood;
};
// The car is *composed* of an engine and a hood. Hence, composition. You are
// also bringing together (i.e. *aggregating*) an engine and hood into a car.
The relationship between abstraction and implementation typically implies inheritance, rather than composition/aggregation; typically the abstraction is an interface or virtual base class, and the implementation is a fully concrete class that implements the given interface. But, to make things confusing, composition/aggregation can be a part of the interface (because, for example, you may need to set/get the objects that are used as building blocks), and they are also an approach to implementation (because you might use delegation to provide the definition for methods in your implementation).
To make this clearer:
interface Car {
public Engine getEngine();
public Hood getHood();
public void drive();
}
// In the above, the fact that a car has these building blocks
// is a part of its interface (the abstraction).
class HondaCivic2010 implements Car {
public void drive(){ getEngine().drive(); }
// ...
}
// In the above, composition/delegation is an implementation
// strategy for providing the drive functionality.
Since you have tagged your question "bridge", I should point out that the definition of the bridge pattern is a pattern where you use composition rather than inheritance to allow for variation at multiple different levels. An example that I learned at college... using inheritance you might have something like:
class GoodCharacter;
class BadCharacter;
class Mage;
class Rogue;
class GoodMage : public GoodCharacter, Mage;
class BadMage : public BadCharacter, Mage;
class GoodRogue : public GoodCharacter, Rogue;
class BadRogue : public BadCharacter, Rogue;
As you can see, this kind of thing goes pretty crazy, and you get a ridiculous number of classes. The same thing, with the bridge pattern, would look like:
class Personality;
class GoodPersonality : public Personality;
class BadPersonality : public Personality;
class CharacterClass;
class Mage : public CharacterClass;
class Rogue : public CharacterClass;
class Character {
public:
// ...
private:
CharacterClass character_class;
Personality personality;
};
// A character has both a character class and a personality.
// This is a perfect example of the bridge pattern, and we've
// reduced MxN classes into a mere M+N classes, and we've
// arguably made the system even more flexible than before.
the bridge pattern must use delegation (aggregation/composition and not inheritance). from the gang-of-four book:
Use the Bridge pattern when
* you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.
* both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
* changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
* (C++) you want to hide the implementation of an abstraction completely from clients. In C++ the representation of a class is visible in the class interface.
* you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" [RBP+91] to refer to such class hierarchies.
* you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class [Cop92], in which multiple objects can share the same string representation (StringRep).
Standard UML of Bridge pattern clears out all air around the confusion. Below is an explanation with a brief example to clear the air around this.
Apologies for this lengthy code, best way is to copy this code to Visual Studio to easily understand it.
Read through the explanation written at the end of code
interface ISpeak
{
void Speak();
}
class DogSpeak : ISpeak
{
public void Speak()
{
Console.WriteLine("Dog Barks");
}
}
class CatSpeak : ISpeak
{
public void Speak()
{
Console.WriteLine("Cat Meows");
}
}
abstract class AnimalBridge
{
protected ISpeak Speech;
protected AnimalBridge(ISpeak speech)
{
this.Speech = speech;
}
public abstract void Speak();
}
class Dog : AnimalBridge
{
public Dog(ISpeak dogSpeak)
: base(dogSpeak)
{
}
public override void Speak()
{
Speech.Speak();
}
}
class Cat : AnimalBridge
{
public Cat(ISpeak catSpeak)
: base(catSpeak)
{
}
public override void Speak()
{
Speech.Speak();
}
}
-- ISpeak is the abstraction that bot Dog and Cat has to implement
-- Decoupled Dog and Cat classes by introducing a bridge "Animal" that is composed of ISpeak
-- Dog and Cat classes extend Animal class and thus are decoupled from ISpeak.
Hope this clarifies