Class Inheritance - oop

I wanted to know the technical reason why a parent object cannot be assigned to a child.
For eg :
Class Animal{}
Class Dog : Public Animal{}
Animal a = new Dog() is possible and but why
Dog g = new Animal() is not possible.
I know that, according to the above relationship Dog " is a " Animal but not Animal "is a" Dog. But what is the technical reason behind it. Why we can't assign it ?

Because dogs bark. Animals, in general, don't.
Dog g = new Animal();
g.bark();
How would g know to bark? Did the assignment magically turn the animal into a dog? What if it was a parrot? How do we turn parrots into dogs? Or if the assignment did not convert anything, how would the parrot know how to bark? (Note that this is a Norwegian Blue parrot, which doesn't really know how to do anything.)

It's both logical and technical reason - an instance of Animal does not have all methods and fields of a Dog. For example:
class Animal {
public int legs;
}
class Dog extends Animal {
public int fangs;
}
Dog dog = new Animal();
dog.fangs = 5;
but you are using an Animal, which does not have fangs, so it would fail.
You can usually downcast though:
public doSomethingDoggish(Animal animal) {
((Dog) animal).bark();
}
But if you have not passed an instance of Dog there, it will fail at runtime.

Because then you could write
Animal animal = new Rabbit();
Dog d = animal;
d.bark(); // but it's a Rabbit

the classic term is "IS-A" as in "a dog IS A(n) animal", but "an animal is NOT a dog", in your relationship.
That is intuitively why you can assign a dog to an animal, but not the other way around.

Because your Dog is an Animal.
Dog g = new Dog()
You now have an Animal. It's a specific type of animal, but still an animal. It can do all the things that an animal can do.
If I want to treat it only as an Animal and ignore the fact that it's a Dog, I can do that with Animal a = new Dog()
An Animal isn't a Dog. It can't do all the things a Dog can do. So if I try to say Dog g = new Animal() ... I'm not making any sense. I'm trying to take away everything that makes a Dog a Dog.

Classes are like contracts. When you define your Animal class you say something like "This is an Animal, he can do this". When you define Dog, you say "Dog is an Animal, He can do everything an Animal do, but he can also do that".
Now, when you do Animal a = new Dog() it is ok, since a Dog can do everything an Animal do.
But when you do Dog g = new Animal(), your breaking your contract, since an Animal can't do "that", only a Dog can.

Since you asked for technical reasons, consider memory storage: "new Animal()" only requires enough resources to store the minimum data required by all animals, but "new Dog()" requires more resources -- the resources of a Mammal (fur, warm blood), and the resources of a Dog (fascination with squirrels).
If, though, you're asking "Once I've written 'Dog' once, why do I have to say it again?" then the answer is "not all languages require that."

Related

How to change object display depending on type?

I though I was ok with POO, but right now I'm all confused with the following.
Basic model
For instance, let's say you've created Dog and Cat objects that extends the abstract class Animal.
abstract Animal has the generic properties:
color: string
legs: number
Cat extends Animal has the extra property:
humansTolerance: number
Dog extends Animal has the extra property:
ballsRetrieved: number
Problem
Now, I want to display a list of all the animals on my application in a generic way. Simple, the application just pulls all the Animal objects from the database, puts them in a nice List<Animal> with each object instantiated with its proper class.
But now, when I click on one given animal, I want to be able to display the Animal generic properties AND the properties that are specific to its type.
For example, If the selected animal is a cat, I want the UI to show the generic animal properties color and legs, but I also want to display the cat property humansTolerance. Same goes for the dog with ballsRetrieved.
Question
Am I supposed to use the often called infamous instanceof / typeof to do that? How can I make the UI display various elements depending on the type of the object?
Use a virtual method or the Visitor Pattern.
The obvious object-oriented approach would be to just have a display() method in the objects. Each "class" displays itself:
class Dog {
...
public display(): void {
...
}
}
I don't know what is "customary" in TypeScript, but the object-oriented approach would hide properties, and offer behavior instead.

OOP - Inheritance

If I have a class, class Animal.
And I have a class Dog and a class Cat both inheriting Animal.
Cat can call methods inside Animal. But can Cat call methods of Dog?
The answer to your question can be answered by stating it like this
Is a cat a dog?
I'll let you answer this one.
No it can not and no it should not (at least not when talking about proper OOP). If a cat really needs a dog (for whatever sick reason) you should inject the dog in the cat. If you think you need it you probably have the wrong inheritance / abstraction.
class Animal
{
public annoy();
}
class Cat extends Animal
{
private $dog;
public function __construct(Dog $dog)
{
$this->dog = $dog;
}
public function annoyDog()
{
$this->dog->annoy();
}
}
class Dog extends Animal
{
}
$dog = new Dog();
$cat = new Cat($dog);
$cat->annoyDog();
Above is an example of injection. Note that as Tony Hopkinson stated you are calling the methods on the instance of dog in this case. You could call methods on the class if they are public static, but since it is tagged OOP you really shouldn't. P.S. example is in PHP.
The methods defined in a superclass are accesible to any subclass. But "sister" classes cannot access the (private) methods of one another.
So if your classes Cat and Dog inherit from Animal, then both Cat and Dog objects can call methods from Animal, but they cannot (must not) access the methods of each other.
If I have a class, class Animal.
And I have a class Dog and a class Cat both inheriting Animal.
Cat can call methods inside Animal. But can Cat call methods of Dog?
in javascript , yes , i'll use coffeescript because it is easier to write :
class Animal
bark:-> "i'm an animal"
class Dog extends Animal
eatBone : -> "i'm eating a bone"
class Cat extends Animal
cat = new Cat
alert Dog::eatBone.call cat
Does it make sense ? probably not, but in javascript methods of a prototype are not bound to an object(unless you force it with closures). Now one could argue javascript doesnt have classes like java , but are C++ classes like Java ones ? python classes like Java ones ? who decides what's a real class or not ?
My point is the question is irrelevant outside of a language context.
Here cat and dog are two distinct classes and there is no direct relation between them.If we wish we can add few codes to link these classes. Until then the members in one cannot be accessed from the other.
If Cat doesn't inherit from Dog then no
I'm afraid that... no. Cat cannon invoke Dog methods.
Inheritance allows to "view" parents (public/protected if you are using Java) methods inside child classes, but not inside siblings classes.
Obviosly if Cat has an instance of Dog as property (I don't know why it should have...) it can call public methods of that Dog instance.
In java context [I have come across OOPs via Java]
No you cannot.
The methods that can be called by an object is determined by the reference variable.
If you use Dog/Cat reference variable it can only access methods in Dog/Cat class(including inherited and overridden ones)
If you use Animal(i.e.Parent Class) as a reference variable and have it refer to a Cat/Dog class object. You can only call the inherited/overridden methods of subclass using that reference variable.This is decided at compile time.[if the fn being called is identified by the reference variable or no]
The Dog class object is unaware of exclusive Cat class functions[other than inherited and overridden ones] so it cant call the methods.
As pointed by others, If u have a case as such u might not be looking for inheritance.

How to decide whether use IS A or HAS A Relation

public class B {
public String getMe()
{
return "Some";
}
}
Assume that i have a above class , by which parameters should we decide what to use ?? Whether is a or Has a Relation ??
HAS - A
public class A {
public static void main(String args[])
{
B b = new B();
System.out.println(b.getMe());
}
}
or
public class A extends B
{
public static void main(String args[])
{
A b = new A();
System.out.println(b.getMe());
}
}
Depends on the logical relation. It just needs to make sense.
Example:
Lets say you have Animal classes.
So you have these classes: Animal, Dog, Cat , Leopard, Fur, Feet
Cat and Dog IS A Animal.
Leopard IS A Cat.
Animal HAS A Fur, Feet.
In a nutshell:
IS A relationship means you inherit and extend the functionality of the base class.
HAS A relationship means the class is using another class, so it has it as a member.
There are 4 types of relations possible :
Generalization (IS A) : Which is implemented using inheritance like you did above. It's used when class A has all the same feature of B and you want to add some more features. So you simply extend B and add the new features.
Aggregation (HAS A) : This is a bit weaker relation than generalization. You use this relation when the object of A owns objects of B or is composed of objects of B (may be among other objects of other classes). The first type is called shared aggregation, the second is called composition. In aggregation and composition there usually an object controlling the life of the other object (it instantiates it and destroys it as it needs).
Association: In association, the classes simply know about each other's so it's weaker than aggregation. The objects do not control each other's life.
Usage : It's the weakest relation of two classes and it means simply that one class may appear as a type in a method parameter or is used internally in code.
In your example, it should be aggregation (HAS A) if A has a field of type B. But if it just creates instance of B to be used in code internally and the object is disposed from memory when the scope ends then it's neither IS A nor HAS A. It's just a usage relation.
In simple term:
"is a" represent the inheritence/extends
"has a" represents the delegation/association
for example:
House is a Building (inheritance)
House has a door(s) (association)
Here is one of the best resources I used for understanding OOP: http://chortle.ccsu.edu/CS151/cs151java.html (part 6 & 10)
is-a is like for example, a Dog is an Animal or a Cat is an Animal or It is like "a person is that-kind of a person". Is-a relationships have other objects' properties, like here "Animal" is a class(object) and etc.
The has-a relationship is like, an object has its own properties, for example, Fish has Gills or pants have pockets ... something like that.

Questions about "casting operation" in OOP

When programming, we usually use some type-casting operations.
When the casting happens on the objects "on the same level", it feels ok. But when it happens on the ojects "on the different levels"(mainly between father and son), it feels weird.
Considering this:
Class Son extends Father
WhenSon s = (Son)father;, it's absolutely unreasonable. Because a "Son" is not a "Father" anymore, "Son" may grow up with some new properties "Father" doesn't have, the casting operation makes these properties unknown.
On the other hand, Father f = (Father)son seems reasonable, but according to LSP
"An instance of a derived should be able to replace any instance of its superclass"
A "Son" can do anything his "Father" can, so the casting operation seems useless.
So can i say that these casting operations are agaisnt OO design principle but necessary?
Casting objects in OOP is usually the product of either class inheritance or interface inheritance. One has to always remember that class inheritance denotes an "is a" relationship, and interface inheritance denotes a "has a" relationship.
Let's go over to your example: Class Son extends Father doesn't sound like a reasonable abstraction, since every male person is a son, but not all of them will be a father. In fact, the opposite might be more applicable: Class Father extends Son because every father is always someone's son.
On the other hand, we could just ditch this whole abstraction and say that we have, instead, a Class Person that can either be a male or a female, a mother or a father, and so on. Each person will have an attribute containing collection of Person with name Children.
In this abstraction, a Person will only be considered a Father if its gender is male and if Person.Children.Count > 0. This is much simpler than defining a Father class in and by itself.
I find questions like these always interesting and it lends itself to some kind of debate I think :)
Here are my thoughts.
In class design I would in this case create a class of Person
class Person
{
public bool IsFather { get; set; } // this variable will change depending on the count of children
public List<Person> children { get; set; }
}
When I create a derived class, the class should be a specialized person and in the case of Father and Son, I wouldn't create a Father class and a Son class.
You've got a bad example of inheritance.
A better one could be
Class Person
{
public void walk();
}
Class Man extends Person
{
public void shaveBeard();
}
Inheritance is the way to represent an is a relationship; e.g. "a Man is a Person".
Using the Objects
Either of these lines is OK.
Person p = new Person();
Person m = new Man();
It is fine to call p.walk on both. However to call the shavebeard() method, m has to be a Man object. For reasons of type safety, you have to cast it to a Man object; e.g. (Man) m.shaveBeard(); The cast here will fail, so it's best to check that the variable refers to an instance of Man:
if(m instanceof Man)
{
(Man) m.shaveBeard();
}
Neither seem reasonable to me. What seems more plausible:
Son s = (Son)person //Valid
Father f = (Father)person //Valid
Here's a hint: the Class on the left hand side is the superclass and that on the right side is the subclass so if we have this:
Object p = new Student(); //is correct
Student s = new Object() //is wrong...it's like saying that every Object is a student..
Care must be considered when doing explicit casting as it may look correct but might not work as expected. You can't instantiate your father's private property to yourself.

Object Oriented Design Interview [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Any advice on solving this problem?
Well, here's one good one that I came up with - utilizing OOP overriding, subclass and superclass:
namespace Animals{
// base class Animal
class Animal{
public void eat(Food f){
}
}
class Carnivore extends Animal{
public void eat(Meat f){
}
}
class Herbivore extends Animal{
public void eat(Plant f){
}
}
class Omnivore extends Animal{
public void eat(Food f){
}
}
}
namespace Food{
// base class Food
class Food{
}
class Meat extends Food{
}
class Plant extends Food{
}
}
I create subclasses Herbivore, Carnivore and Omnivore from the superclass Animal and override the eat method with the type of food that it can actually eat.
So:
Plant grass = new Plant();
Herbivore deer = new Herbivore();
deer.eat(grass); // ok
Plant grass2 = new Plant();
Carnivore tiger = new Carnivore();
tiger.eat(grass2); // not ok.
Meat deer2 = new Meat();
tiger.eat(deer2); // ok
Well, the final problem is that, when you specify that deer is a Herbivore, you can't make it a Meat for tiger to eat. However at the end of the day, this should be sufficient for solving the interview problem whilst not putting the interviewer to sleep.
There's a wonderful poster for the Liskov Substitution Principle that says, "If it looks like a duck, quacks like a duck, but needs batteries, you've probably got the wrong abstraction." And that's the quick answer - some of the objects can be both animals and food, so unless you're willing to go the route of multiple inheritance, then the classification schema is all wrong.
Once you've cleared that hurdle, the rest is open-ended, and you can bring in other design principles. For instance, you could add an IEdible interface that allows objects to be consumed. You might go aspect-oriented, and add decorators for carnivore and herbivore, and that would allow consumption of only the right class of objects.
The point is to be able to think on your feet, to see and explain various aspects of a problem, and to communicate well. And perhaps not to get stuck on a "one right answer" limitation.
I'd tell him to scratch that. It's a horrible abstraction. Not to mention we're not given any context. Abstractions don't come out of thin air, or out of an "idea" of what's "right". Show me what problem are you trying to solve first, so we can evaluate this abstraction.
If no context is provided, then I'll just assume/make-up my own: you want some types of objects to be able to eat other types of objects. Nothing more, nothing less.
Make an Eatable interface (or you can call it Food, if you want), and since we have no context what so ever, I'll assume it's a toy console program, that just prints:
<X> ate <Y>
so all we need for this interface is a getFoodName() method.
For error checking, you can create a bunch of isXFoodType methods, for instance, isGrassFoodType(), isMeatFoodType(), etc. The Cow's implementation of Eat(Eatable e) would check for isGrassFoodType(), and when fails, prints:
"Cow can't eat " + e.getFoodName()
Alan Kay, who coined the term "object-oriented programming", has said "OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things".
Trying to fix this "problem" in the data model sounds to me like the opposite of late-binding: why do you need the compiler to enforce this? I wouldn't worry about changing the model at all. If you're passed something you can't eat, you throw an exception -- just like in real life, pretty much!
Food should be an interface, therefore Plant and Animal could be Food too.
abstract Animal class should have eat method that take Food as parameter.
subclasses of Animal: Carnivore, Herbivore and Omnivore should have their own version of eat.
For example for Carnivore:
private void eat(Food food)
{
if(food instanceof Animal)
{
happilyEat();
}
else
{
sniff&TurnAway();
}
}
The Problems solved.
But for a better design, Carnivore, Herbivore and Omnivore should be interfaces too, as they are not the proper way of tagging the animals.
This is easy with Generics in C# btw:
public class Food
{
}
public abstract class Animal<T> : Meat where T:Food
{
public abstract void Eat(T food);
}
public class Herbivore : Animal<Plant>
{
public override void Eat(Plant food)
{
Console.WriteLine("Herbivore eats plants.");
}
}
public class Omnivore : Animal<Food>
{
public override void Eat(Food food)
{
Console.WriteLine("Omnivore eats food.");
}
}
public class Carnivore : Animal<Meat>
{
public override void Eat(Meat food)
{
Console.WriteLine("Carnivore eats meat.");
}
}
public class Plant : Food
{
}
public class Meat : Food
{
}
public class Cow : Herbivore
{
}
public class Tiger : Carnivore
{
}
public class Human : Omnivore
{
}
Usage:
var human = new Human();
var tiger = new Tiger();
var cow = new Cow();
var plant = new Plant();
human.Eat(cow);
tiger.Eat(human);
cow.Eat(tiger); // this doesn't compile
tiger.Eat(plant); // neither does this
Here's some thoughts on that interview question:
I agree with Cylon Cat: This kind of abstraction doesn't work well without multiple inheritance (even if it's Java-like interfaces.)
I would create two forms of inheritance:
Animal:
Carnivore
Herbivore
Food:
Meat
Vegetable
The "eat" method of the two kinds of animals (I'm ignoring omnivores, insectivores, and many other kinds) would be specialized for the different kinds of food. If we're using a language like Java, then Food would be an interface.
Any animal is food, any vegetable is food. And in fact a tiger can be eaten by a cow. (The prion disease scrapie is spread by feeding infected sheep neural tissue to uninfected sheep.)
You could have a hierarchy of species, ala Linnaeus, both animal and vegetable. Each species is a Singleton, and it has a List<Species> that records its typical diet. Ditch the Food hierarchy entirely, it only confuses things.
And, if your only problem is recording diet for each species, then the multiple Species classes are unnecessary. Just have a single Species class with the species name as one instance variable and the List<Species> as another.
There's no one best solution. You might want to make this a community wiki, as that's generally the accepted practice for subjective questions.
I'd think about what actually would make the best parent class for the hierarchies, and try to figure out what "best" means in that context.
Everything there are Things, which could have a Name attribute. But everything there at some level is Food; if it can eat something, something can eat it. I might make Food the parent class, and give it a method that returns a boolean to check if the parameter object can eat the current object.
So,
class Food {
boolean canBeEatenBy(Food hungryObject)
String name
}
That seems the simplest class hierarchy that fits everything I might need on a first pass?
That said, the important part in most interview questions is the feel you get for the interviewee, not so much the exact answer that they give.
Double dispatch, perhaps?
If you expect the system to get very big I would suggest subclassing plant/meat and herbivore/carnivore/omnivore.
Ensure the system has a standard interface for all plant/animals called getFoodName() and getFoodType(), you could enforce this by creating a parent class for plants/animals called species.
The problem I would see with the subclassing plant/meat and carnivore/herbivore is that a meerkat is carnivore but it likely can't eat a rhino(there may be a better example), so some restrictions are needed beyond "I eat meat, you eat plants".
If it wasn't going to get incredibly big and you wanted to be neurotic about it, you could store static enums of allowable foods for each subclass of animal. So tiger could store deer, antelope etc.