Benefit Of Object assigned to another object in java - java

im a beginner in java and i study everyday from books . there is a quistion that press my brain so hard for so long , what is usefulness of creating an object and give it an another object refrences ! i saw too many examples of this format .
Cat simon = new Cat();
Animal tiger = simon;

The main purpose of an Object reference by itself is to tell Java to keep the Object around. Otherwise, the memory used in that Object will go away (reclaimed by the Garbage Collector). And, with the reference, you can trigger actions on the Animal (like simon.eat() and simon.sleep()). Without the reference, you couldn't do this. Anything you work on in any program must stay around by having some reference to it (like you did above).
The Object reference between Animal and Cat shows that "I can treat Cat, Dog, Elephant, Eagle, Moose, etc. any animal that is an Animal like an Animal." (This is called polymorphism.)
So, an Animal can have actions like eat() and sleep() because all Animals can eat() and sleep(). But, an Eagle can also fly(). So, Eagle has the fly() action defined. And, you wouldn't put the fly() action in Animal because not all Animals can fly().

This can be useful in cases in many different cases (although as a general term this refers to Polymorphism), one I can think of is a Parent array creation. (Parent being the Animal class in this case, which is further extended by Cat).
Animal[] animals = new Animal[] { simon, dog };
You can reference every item in the list simply by using Animal parent type, you don't have to worry about it being further of type Dog or Cat etc.
So suppose you iterate over this and call the sound()/voice() method for each element. If the method is defined in the Parent class (i.e. Animal), you can simple do:
for (Animal animal : animals) {
System.out.println(animal.voice());
}

Related

What is the point of Object Implicit type casting?

I have been banging my head to understand the real use of Object type casting in java and why it is even there. See example below.
My question is in the form of comments below.
Please don't suggest me to go reach somewhere. I have already done that. Please answer me directly if you know. Thanks.
Check this code with method 'scream' overridden I am not getting compile time error. Watch comments too
Animal aniObj = new Animal();
Animal dogAniObj = new Dog();
Dog dogObj = new Dog();
ArrayList<Animal> animalArrayList = new ArrayList<Animal>();
animalArrayList.add(aniObj);
animalArrayList.add(dogAniObj);
animalArrayList.add(dogObj);//Here when I am able to add the Dog object there no point in creating dogAniObj above
aniObj.scream();//Calls scream of Animal
dogAniObj.scream();//Calls scream of Dog
dogObj.scream();//Calls scream of Dog. Then why do i need above statement? Why to attain polymorphic behavior when we can directly call scream method with the Dog object when needed?
This is what Java gives you as Runtime Polymorphism, at runtime what is the object reference it has, that method instance will be called.
Think that you are writing some generic lib/framework then all you want use is Animal class which is base to all other sub classes like Dog, Cat etc then you can not declare your members like Dog myDog or Cat myCat there it should be Animal myAnimal so that it can take all the animal subclasses.
Thast's why animalArrayList should always take Animal and its variants no compilation error comes.
You never know Animal class can be extended by your lib users to create many other Animal classes.

Factory Design Pattern and Diamond OOP issue

In one of my projects, I have to implement the Factory design pattern to solve a specific issue.
I have one parent interface and two child interfaces. In the next stage, I have to create a factory which will return an instance of a specific class based on given input.
Please see my sample code below which explains my problem and the sample diagram as well.
Sample Diagram
Sample Code
enum AnimalType{ DOG, CAT }
Class Factory{
public Animal getInstance(AnimalType animalType){
Animal animal = null;
switch(animalType){
case DOG: animal = new Dog();
break;
case CAT: animal = new Cat();
break;
default:
break;
}
return animal;
}
}
/*Actual Problem */
Animal animal = Factory.getInstance(AnimalType.DOG);
/* When I use any IDE like IntellijIdea or Eclipse it only provides eat() method after animal and dot (ie. animal. ) */
animal.<SHOULD PROVIDE eat() and woof() from Dog> but it is only providing eat()
Any advice to overcome this problem? Or, should I consider any other Design Pattern for this problem?
Your problem is not directly related to the factory pattern. You are declaring an Animal and then want to treat it as a Dog. It doesn't matter how you create it you will need to make it a Dog to call doggy methods.
You have many options to resolve this. Here are a few alternatives.
Have separate methods for creating different extensions of Animal. So instead of Animal getInstance(AnimalType type) you would have Dog getDog() and Cat getCat() methods in the factory. Given the factory needs to be aware of all these classes anyway this seems like the best option to me.
Continue to return Animal instances from your factory but then use the 'visitor' pattern to treat dogs and cats differently.
Use instanceof and casting to treat animals as dogs or cats. This is not recommended for most situations but is suitable in some cases.
I think your problem is related to "General OO" not really about Factory design pattern. Now let's take a look at your three interfaces: Animal, Dog and Cat. The Dog and Cat are implemented the Animal interface, it does not mean that they have exactly the same behaviors with difference implementations, what we can make sure is they will respect the behaviors of Animal.
For instance:
The Dog and Cat will have the same behavior is eat()
The Dog has a woof() behavior which do not exist in the Cat
The Cat has a miaw() behavior which do not exist in the Dog
Therefore, when you implement the Simple Factory (according to Head Of Design Pattern it is not real design pattern, just a programming idiom) to deal with create object and return the Animal interface, it means you are considering the Dog and Cat as an Animal with the same behavior is eat(). That's why you can not do somethings like this in your code
/*Actual Problem */
Animal animal = Factory.getInstance(AnimalType.DOG);
/* When I use any IDE like IntellijIdea or Eclipse it only provides eat() method after animal and dot (ie. animal. ) */
animal.<SHOULD PROVIDE eat() and woof() from Dog> but it is only providing eat()
In my opinion, there are some possible implementations:
For simplicity, you can create 2 Simple Factory, one for Dog and other is Cat
If you know what you want, you can cast the Animal to Dog or Cat, and then use their functions
Implement the Abstract Factory pattern, it will provide and abstract interface for creating a family of product (Dog and Cat).
I hope it can help you.

Why Java needs explicit downcasting?

I have seen other answers to similar questions but all of them rely on the fact that the language is defined to be like this. Following is what I am seeking an explanation to:
In an inheritance hierarchy, the parent types can hold child objects implicitly (why?), however for the child references to hold a parent object, explicit downcast is necessary (why?).
Please cite some example that explains why not doing this will fail, I mean using Animal, Dog type etc. If this question is already answered and I have missed it, citing that also will be helpful.
For example:
class Animal{
public void eat(){};
}
class Dog extends Animal{
public void bark(){};
}
class App{
Animal an = new Dog(); //1. why can animal store a dog but not a dog store an animal
Dog dog = (Dog) new Animal(); //2. Dog has the behavior of an Animal so why explicit downcast
}
I just want to know how this lines make sense, other than just knowing they are language semantics. Better if your answer looks like that as a granny explaining this to her grandchild.
Edit:
I just was wondering that Dog inherits Animal and has all the behavior. Hence number 2 above should have been allowed without explicit downcasting.
Or, that (I think I got it now) when I ask a Dog to store an Animal there are possibilities that I actually get a Cow or a Horse, because Animal being parent can hold any of its subtypes. If that's the case then why has Java allowed Animal to hold subtypes since there might be behavior typical to subtypes like a Dog will bark(), for that again compiler has to check and report. I know the rules just trying to reason out in the simplest of sense.
The gain of strict type binding in Java is that you get compile time errors, instead of runtime errors, when possible.
Example:
class Animal {
void eat() {}
}
class Dog extends Animal {
void bark() {}
}
class Pigeon extends Animal {
void pick() {}
}
class MyFunction {
void run() {
Animal first = new Pigeon();
// the following line will compile, but not run
((Dog)first).bark();
}
}
If you have such code in a simple example like this, you will spot the problem at once. But consider having such a problem in a project, in a seldom called function at the depth of thousands of lines of code, in hundreds of classes. One day in production, the code fails and your customer is upset. And its up to you to find out why it failed, what happened and how to fix it. Its a horrible task.
So, with this somewhat complicated notation Java nudges you into thinking again about your code, the next example would be how its done better:
class MyFunction {
void run() {
Pigeon first = new Pigeon();
// the following line will NOT compile
first.bark();
// and neither will this. Because a Pigeon is not a Dog.
((Dog)first).bark();
}
}
Now you see your problem at once. This code, will not run. And you can avoid the problems ahead by using it correctly.
If you make your Animal class abstract (which you should), you will see that you can only instantiate specific animals, but not general ones. After that you will start using the specific ones when required and be relieved that you can reuse some code when using the general class.
Background
Conceptually, runtime errors are harder to find and debug, then compile time errors. Like, seriously hard. (Search for NullPointerException here on Stack Overflow and you will see hundreds of people who struggle to fix runtime exceptions)
In a Hierarchy of things (in general, not programming related) you can have something general "Thats an animal". You can also have something specific "Thats a dog". When someone talks about the general thing, you can't expect to know the specific thing. An animal can't bark up a tree, because birds could not, neither do cats.
So, in Java in particular the original programmers found it wise to decide that you need to know an object specific enough to call the functions of that object. This ensures that if you didn't pay attention, the compiler will warn you, instead of your runtime.
Your particular case
You assume that:
Dog dog = (Dog) new Animal();
should work, because a Dog is an Animal. But it won't, because not all Animals are Dogs.
BUT:
Animal an = new Dog();
works, because all Dogs are Animals. And in this specific case
Animal an = new Dog();
Dog dog = (Dog)an;
will work too, because the specific runtime state of that animal happens to be Dog. Now if you change that to
Animal an = new Pigeon();
Dog dog = (Dog)an;
it still WILL compile, but it WILL NOT run, because the second line Dog dog = (Dog)an; fails. You can't cast a Pigeon to a Dog.
So, in this case you WILL get a ClassCastException. Same if you try to cast new Animal() to Dog. An Animal is NOT a Dog. Now, that will happen at runtime and that is bad. In the Java way of thinking, compile time errors are better then runtime errors.
Yes. One simple real time example to understand the theory is
Every Truck driver is Driver but not you cannot say every Driver is a Truck Driver.
Where
Driver -Parent
Truck Driver - Child.
Animal an = new Dog(); //1. why can animal store a dog but not a dog store an animal
You ordered for an Animal and the shop keeper gave a Dog for you and you are happy since Dog is an Animal.
Dog do = (Dog) new Animal(); //2. Dog has the behavior of an Animal so why explicit downcast
You are asking for a Dog and the shop keeper gave an Animal to you. So it is so obvious that you check that the Animal is a Dog or not. Isn't you ?? Or you just assume that you got a Dog ?
Think.
In java references are used. Suppose we have below classes
class A{
Integer a1;
public A(){
// a1 is initialized
}
public void baseFeature(){
super.baseFeature();
// some extra code
}
}
and
class B extends A{
Integer b1;
Integer b2;
public B(){
super();
// b1 , b2 are initialized
}
#Override
public void baseFeature(){
super.baseFeature();
// some extra code
}
public void extraFeature(){
// some new features not in base class
}
}
Below all 3 statements are valid
A a = new A();
B b = new B();
A b1 = new B();
In java references are used to refer to the objects kept in Heap.
A reference of type A should not be considered as if it can not hold the objects which have more memory required than an object of class A. Its the references and not the objects holders.
In case of sub type object creation, Constructor call follows : Parent-constructor call followed by constructor call of the actual class whose object is being created.
Sub class object can be said to be having features at-least as much as the Parent type has.
A b = new B() has no confusion, as object of B has all the features of its parent.
Sub class object has all the features as defined in its parent, so any parent class method can be called on the object of sub class
Sub classes can have much more features, which parent class does not have, so calling a method of sub class on object of parent will lead to problems.
Suppose In Java B a = new A() is valid then if a.extraFeature() is invoked then it is obvious of an error.
This is prevented by compile time error. If in case downcasting is needed, then the programmer must do it with extra care. This is the intention of compile time error. Below cases down-casting would not lead to issues but the onus is on the programmer to see if situation is of this kind or not.
public void acceptChild(Child c){
c.extraMethodNotWithParent();
}
Parent p = new Child();
acceptChild((Child)p);
Here programmer is given compile time warning if down-casting is not done. Programmer can have a look and can see if the actual object is really of sub class type then he/she can do explicit down-casting. Thus issues will only come if the programmer has not taken care.
All the replies here help. I was confused.
Removing all the chains in my brain, if I simply think, it now looks like:
Parent can hold subtypes.
You mean thats the benefit of polymorphism and how its achieved.
Child types can hold parent but need explicit downcast.
Since polymorphism is allowed, this downcast is a safeguard. The compiler is asked to trust that the Animal in code is actually going to be a Dog instance that the Dog type wants to hold.
This is because inheritance is specialization, when you inherit a class T, the child class S is a specialization of T, for that Java don't need a cast, but T can have many childs, S' inherits T, S' too, so here if you have an object of S and its referenced as T and you want to get your origin type again, you should make a cast to S and Java check the type at runtime.
an example :
A man and a woman are humans, but a human is a man or woman.
Man man = new Man();
Human human = man //Legal.
Man man2 = (Man) humain; //Legal
Woman human = (Woman) humain; //Error, Java can't cast the humain to Woman, because its declared originaly as Man.
If Java is sure made the cast implecitly, if not, it reports it and don't decide in your place, This check is made at runtime.

confusion with java method overloading [duplicate]

This question already has answers here:
Calling overloaded inherited methods using super class reference
(10 answers)
Closed 6 years ago.
I'm currently working through a Java Book and i've started reading about inheritance and polymorphism.
I'm making a test program that stores animal information, and I want to overload the method that sets the animals size. The user knows the sizes of the dog, but no other animals, so sets animal size to 0 if it's not a dog, and for the dog, it uses its own setSize method with parameters.
However i've tried two methods of creating a dog, by creating an animal object and also by creating a dog object. I assumed that even though the testDog1 variable is of type Animal, it would still be able to overload methods from the Dog class as it is a dog object.
Could anyone please explain why testDog1 does not work but testDog2 does work?
public class Loader {
public static void main(String[] args){
int dogSize = 100;
Animal testDog1 = new Dog();
testDog1.setSize(dogSize);
Dog testDog2 = new Dog();
testDog2.setSize(dogSize);
}
}
public class Animal {
public int size;
public void setSize(){
size = 0;
System.out.println(size);
}
}
public class Dog extends Animal {
public void setSize(int dogSize){
size = dogSize;
System.out.println(size);
}
}
If you are going to refer to testDog1 in your code, the compiler will consider it to be of class Animal. Meaning you can reassign it with an instance of Cat or Bird or anything else, where setSize(int) doesn't exist.
After testDog1 was declared of type Animal, you need to comply with the contract of that class.
The fact that it is currently a Dog doesn't make the specific methods of Dog visible. You will probably learn about casting in the next chapter of the book, though.
Animal testDog1 = new Dog();
An instance of Dog would be created and assigned to the testDog1 variable only when you run the program. ie.) Runtime.
Compiler doesn't run the program or make hard and fast assumptions of what the nature of each statements or variables would be while checking for correctness.Had that been the case , the following stmt would have been a compile time error too.
Animal testDog = null;
testDog.setSize(); // How can you call setSize() on null right? for the same reason mentioned above.
At compile time, all that the compiler knows is that in testDog1 you will have a reference to an Animal. Since an Animal does not have a setSize(int), the compiler cannot locate it and it fails.
It is important to know which operations are done at compile time (the compiler knows the type of the variable) and which one are done at runtime (the runtime knows the actual instance of the object).
Your testDog1 does not find setSize(int dogSize) method in Animal Class Hence it is a compilation error.
where as testDog2 find setSize(int dogSize) method in Dog class and it will compile.
testDog1 is an Animal object. Without casting it as a Dog, it doesn't know that setSize(int) exists.
(Dog)testDog1.setSize(dogSize) tells the compiler that it's actually a Dog.

Polymorphism vs Inheritance

Suppose I have two classes: Animal and Dog. Dog is a subclass of Animal. I do the following code:
Animal a = new Dog();
Now I can call methods of the Dog class through the a variable.
But my question is this: if I can call all of Animal's methods through the Dog objects (inheritance) than why should I use the polymorphism principle? I can just declare:
Dog d = new Dog();
With this declaration can use all of Animal's methods and Dog methods. So why use polymorphism? Thank you very much for your answer.
In Java, the concepts of polymorphism and inheritance are "welded together"; in general, it does not have to be that way:
Polymorphism lets you call methods of a class without knowing the exact type of the class
Inheritance lets derived classes share interfaces and code of their base classes
There are languages where inheritance is decoupled from polymorphism:
In C++ you can inherit a class without producing polymorphic behavior (i.e. do not mark functions in the base class with virtual)
In Objective C you can implement a method on an unrelated class, and call it from a place that knows only the signature of the method.
Going back to Java, the reason to use polymorphism is decoupling your code from the details of the implementation of its counter-parties: for example, if you can write a method Feed(Animal animal) that works for all sorts of animals, the method would remain applicable when you add more subclasses or implementations of the Animal. This is in contrast to a Feed(Dog dog) method, that would be tightly coupled to dogs.
As far as the
Dog d = new Dog();
declaration goes, there is no general reason to avoid this if you know that the rest of your method deals specifically with dogs. However, in many cases the later is not the case: for example, your class or your methods would often be insensitive to the exact implementation, for example
List<Integer> numbers = new ArrayList<Integer>();
In cases like that, you can replace new ArrayList<Integer>() with new LinkedList<Integer>(), and know that your code is going to compile. In contrast, had your numbers list been declared as ArrayList<Integer> numbers, such switchover may not have been a certainty.
This is called "programming to an interface". There is a very good answer on Stack Overflow explaining it.
You can have other implementations of the Animal class, such as Cat. Then you can say
Animal a = new Dog();
Animal b = new Cat();
You can call methods of the Animal class without caring which implementation it really is, and polymorphism will call the correct method. E.g.
a.speak(); // "Woof"
b.speak(); // "Meow"
Really, it's not "Polymorphism vs Inheritance" but "Polymorphism using Inheritance".
Polymorphism allows you to write a method that works for any Animal:
public void pet(Animal animal) {
...
}
This method would accept Dog, Cat, etc, including subclasses of Animal that are yet to be written.
If the method were to take Dog, it would not work for Cat etc.
If you are certain that it will always be a dog there is no reason for it. You might aswell use Dog d = new Dog(); as you described. But let's say you used a method instead of a constructor. The method returned an animal and you wouldn't know which implementation of animal you would get. You would still be able to use the same methods on the animal (even if it's a Dog, Elephant cat etc).
For extensibility purposes inheritance simplifies things. When you want to create an elephant or cat which also share some animal methods, You can easily get those by having animal as super class.
Normally the question you've asked is more similar to Inheritance vs Composition :) More "real life" example of why it's good to use polymorphism is for example usage of strategy design pattern. You can have many TaxPolicy implementation: UsaTaxPolicy, CanadaTaxPolicy, EuTaxPolicy, etc. If you have method calculateFinalPrice, which have to also calculate tax, then you inject the proper implementation and good calculation is executed, no matter you've passed Usa, Canada or Eu implementation.
inheritance is the dynamic polymorphism. I mean when you remove inheritance you can not override anymore.

Categories

Resources