difference of two different allocations of subclass - java

Animal is the parent class of Cat class.
public static void main (String[] args)
{
Animal myCat1 = new Cat; //Allocation 1
Cat myCat2 = new Cat; //Allocation 2
}
What is the diffrerence of two allocation??Each is true ,isn't it?

Animal myCat1 = new Cat();
This is called polymorphism where the super class reference can hold a sub-class object.
Read Java tutorial: Polymorphism

Neither of these are valid. You need (). Apart from that:
the first referes to the instance by its superclass
the second refers to it by its class
You can refer to any object by any of its superclasses, up to Object. This is polymorphism.

To answer your questions:
There is no difference - in both cases 'new Cat ()' allocates an instance of the Cat class.
Both are true - myCat1 is an animal (in fact, a Cat) and myCat2 is a Cat.

Related

Superclass obj = new subclass(); meaning and casting

If I have super class (Animal) and a sub class (Cat).
What does the third point mean? And when we have to cast?
Cat obj = new Cat(); means creating an object from Cat class
Animal obj = new Animal(); means creating an object from Animal class
Animal obj = new Cat();
First lets understand Class, reference and Object. Suppose we have a class named SomeClass
SomeClass ref = new SomeClass();
Above we have an Object of SomeClass created in Heap and a reference variable refers to it. We have named the reference variable as ref. Object is present in heap and we can just access it using a reference. So Object type is of the actual class (on which new keyword has been applied). Reference variable type can be of actual class or its Parent class.
Now let us see the relationship of Inheritance. A class inheriting from another class share a Child-Parent relationship.
Child inherits the behaviour of its Parent and can then override some of the behaviour and also can add some additional behaviour. Hence Object of Child can be used at any place where Parent object is expected, as Child has all the behaviour of its Parent so invoking any behaviour present in the Parent will be handled by the Child.
Parent class do not know about the additional behaviour of its child class ( child class is written later in time.) Hence object of Parent can not be used at the places where Object of Child is expected (If additional behaviour of Child is invoked on Parent object then it will not be honoured).
Now let us assume we have classes ParentClass and ChildClass such that ChildClass inherits ParentClass
ParentClass reference = new ParentClass(); // Valid
ParentClass reference = new ChildClass(); //Valid
ChildClass reference = new ChildClass(); //Valid
ChildClass reference = new ParentClass();// Not Valid.
Note that
ParentClass reference = new ChildClass(); // Here Object is of type ChildClass and Reference is of type ParentClass.
Now when to cast. Any place expecting the object of ParentClass, there is no need to cast, both the objects (of ParentClass or of ChildClass) are fine.
Any place expecting the Object of type ChildClass but if we have a case like below then casting is needed.
public void someMethod(ChildClass expected){
//some implementation
}
ParentClass ref = new ChildClass();
someMethod(ref);//Invalid : Compilation Issue
someMethod((ChildClass)ref);// Valid
ParentClass anotherRef = new ParentClass();
someMethod(anotherRef); // Invalid : Compilation Issue
someMethod((ChildClass)ref); //Invalid, compiles but Runtime it will fail.
Thumb rule : Child is Child, Child is Parent, Parent is Parent , Parent is not Child.
Another example for understanding.
public abstract class List{
public abstract void add(int element);
public abstract void remove(int element);
public int size();
}
public class Application{
private List listReference;
public void setList(List ref){
listReference = ref;
}
}
//Now you may create sub classes as below
public class ArrayList extends List{
// all the abstract methods of List have been implemented
}
public class LinkedList extends List{
//all the abstract methods of List have been implemented
}
Now in main method you can pass ArrayList or LinkedList or any other implementation.
public class Init{
public static void main(String[] args){
Application app = new Application ();
app.setList(new LinkedList());
//or you can set it like this
List listRef = bew ArrayList();
app.setList(listRef);
//or you can set it like this
LinkedList linkedListRef = new LinkedLiet();
app.setList(linkedListRef);
}
}
Notice that the method setList() accepts List type of reference and we can provide any implementation of the List abstraction. This leads to a flexible design.
Classes should be dependent on the abstraction. Programming to interface is a Design Principle which leads to easy maintenance of the application code.
The reason why this is confusing on the face of it is that it is not something that you would typically do in real code, except in the case of a Factory.
As hinted at in Zabuza's comment, you can do this because a Cat 'is-a' kind of Animal and so you can assign an object of type Cat to an object of type Animal. But you can't do the assignment the other way of course, because an Animal is not a kind of Cat.
Now, there are some lurking issues that come with actually being able to create an instance of the the supertype as well as the subtype that mean you typically wouldn't actually do this in real code because it complicates a lot of things down the road. What you would more likely do is make Animal an interface and have a GenericAnimal class that implements it, along with having Cat implement it.
Say you have an object that represents a zoo, and most zoos typically have a collection of animals. The most obvious way to represent this would be this:
java.util.Collection<com.myproject.Animal> zooAnimals;
So now imagine the zoo builds a new habitat, and it's for a lion. For the sake of the story assume we have a very lazy data model and instead of having a specific com.myproject.animals.cats.Lion subtype we just said "lions are cats, close enough". So to update the data structure that tracks all the animals and their names and addresses and favorite foods and whatever else, we might do this:
com.myproject.Animal newArrival = new com.myproject.animals.Cat("Larry the Lion", "Africa Exhibit", "Gazelles");
zooAnimals.add(newArrival);
Now imagine that the zoo continues to grow, and gets an Ostrich in the Africa habitat. And the same lazy data model applies so we just call it a Bird.
com.myproject.Animal newArrival = new com.myproject.animals.Bird("Oliver the Ostrich", "Africa Exhibit", "Whatever Ostriches Eat");
zooAnimals.add(newArrival);
Now actually writing that exact code would normally only happen in very specific cases inside a factory object or something, and realistically type hierarchies like this have a tendency to not work very well in practice at all, contrary to what a lot of us learned in Object Oriented Programming class, but for the sake of the question that is an example situation where you might do what you are asking about.
Lastly, you also asked when you have to cast. You would have to do this if you had code that needed to know about any special methods or fields that the Cat or Bird types have that Animal does not have. For instance the Cat type might have a property called tailLength because cats typically have tails and for whatever reason the zoo likes to keep track of that. Similarly the Bird type might have a property called wingSpan because birds have wings and we want to keep track of how big they are. The Animal type doesn't have any of these properties so if we get the object for the lion or the ostrich out of the zooAnimals collection (and maybe we looked at the name or something to figure out it was the lion) we would have to cast back to the Cat type in order to access the tailLength property. Same thing for the ostrich and it's wingspan.
for( Animal theAnimal : zooAnimals ){
if( theAnimal.getName().equals("Larry the Lion") ){
Cat theCat = (Cat)theAnimal;
System.out.println("Larry's tail is " + theCat.getTailLength() + " inches long";
}
else if( theAnimal.getName().equals("Oliver the Ostrich") ){
Bird theBird = (Bird)theAnimal;
System.out.println("Oliver's wingspan is " + theBird.getWingSpan() + " inches";
}
}
Again you probably wouldn't actually do something like that in real code, but perhaps it helps to illustrate the example.

method chaining, returning an object from a list and getting values from it

what I have is a list of Dog objects, in the objects there contains a value that is a Boolean to show whether the dog as completed a training or not. What im trying to do is iterate over the list and only return Dog() objects that have completed training, for instance if their are 12 dogs, and only 3 have completed training, the loop should only print those objects.
else if (input == 1) {
for (int i = 0; i < 12; ++i) {
//Create a temporary value to hold the object.
Object tempHold = dogKennel.getAnimal(i);
//If animal has not graduated, skip, else print.
if (!(tempHold.getGraduation())) {
continue;
}
else {
System.out.println(dogKennel);
}
}
getAnimal(i) returns the object at int i
the method .getGraduation is defined and does return a Boolean however the compiler doesnt want to recognize temp value as is, and doesnt go beyond that value. the compiler keeps suggesting to cast tempHold, but even if I do, it doesnt work.
i feel like it would work if i could get it to compile, as the object that is returned would have a getGraduation() method (it is defined for the super class of the animal.)
however the compiler doesn't want to recognize temp value as is, ...the compiler keeps suggesting to cast tempHold, but even if I do, it doesn't work.
The compiler is telling you two things:
An Object is NOT a Dog (the opposite is true. A Dog is an Object).
class Object does not have method isGraduated() defined for them.
To fix this, you can cast Object to Dog:
Dog tempHold = (Dog)dogKennel.getAnimal(i);
Now that we have a Dog, we can safely invoke isGraduated() on it. But the problem is we canNOT be sure that we have a Dog. We may as well have a Cat if we get the Animal from another kennel. In that case, you will get a ClassCastException which tells you that Cats cannot be cast as Dogs.
To avoid getting run time exceptions, you can add a check:
Object tempHold = dogKennel.getAnimal(i);
if(tempHold instanceof Dog) {
Dog dog = (Dog)tempHold;
System.out.println(dog.isGraduated());
}
The instanceof check fixes the problem.
There are ways to avoid this run time check altogether. One would be to create an interface:
public interface CanGraduate {
default boolean isGraduated() {
return false;
};
}
Then make all Animals implement this interface:
public abstract class Animal implements CanGraduate {
//Behavior common among all animals
}
You can now freely add new animal types and be assured that you can safely invoke isGraduated() on them and get a false value as long as they inherit from the above Animal class.
For dogs, isGraduated() is supposed to be more meaningful. So you can override it in their case:
public class Dog extends Animal {
private boolean _graduated = true;
#Override
public boolean isGraduated() {
return _graduated; //or some complex logic that determines graduation
}
}
With this structure, you no longer need to worry about invoking the method on any kind of Animal.
As an example, let us see some driver code:
public class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
Dog dog2 = new Dog();
Cat cat1 = new Cat();
Cat cat2 = new Cat();
List<Animal> dogKennel = List.of(dog1, dog2);
List<Animal> catKennel = List.of(cat1, cat2);
for(Animal x : catKennel) {
System.out.println(x.isGraduated());
}
}
}
The program will simply output false since Cats can never graduate. If the kennel contained Dogs, it would output the actual graduation status of the dog.
Like the others have said, the getGraduation() method is only defined presumably in the Dog class. This means that the method can only be called on Objects with the type Dog. To define a variable with type Dog you can do Dog temphold = *whatever*. The reason it wants you to cast is because Object is a supertype of Dog. If you'd like to read more about casting you can here: https://javarevisited.blogspot.com/2012/12/what-is-type-casting-in-java-class-interface-example.html
Basically, all you have to do is a cast to convert the object
if (!(((Dog)tempHold).getGraduation()))
{
continue;
}
this casting tells the compiler that even though tempHold is an object of the Object class it also is an object of the Dog class and should have all of its properties
If you want to filter the list for just ones with a certain condition, the most common way to do that these days is with the Stream::filter method.
It would look like this:
List<Dog> completedTraining =
dogKennel
.stream()
.filter(
dog -> !dog.getGraduation()
)
.collect(
Collectors.toList()
)
;

What is the difference between compile time linking and run time linking?

I am currently reading a book and stuck at following code:
public class TestAnimals {
public static void main (String [] args ) {
Animal a = new Animal();
Animal b = new Horse();
a.eat(); // Runs the Animal version of eat()
b.eat(); // Runs the Horse version of eat()
}
}
class Animal {
public void eat() {
System.out.println("Generic animal eating generically");
}
}
class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay, oats, horse treats");
}
public void buck() {
}
}
Please have a look at the commented lines.
The book goes on to say "To reiterate, the compiler looks only at the reference type, not the instance type". Really? Had this been the case, both a.eat() and b.eat() would produce same result, as they (a and b) have same reference type (which is Animal).
Also to me this seems to be the compile time binding because virtual keyword has not been used but in the book results are of run time binding. I am so confused at this point. Any help would be greatly appreciated.
The compiler does indeed look only at the statically known type, not the actual runtime type of the instance - after all, Java is a statically typed language. As a matter of fact, in all but the most trivial cases, the compiler can't even know the runtime type of an object reference (as to solve this problem for the general case, it would have to solve undecidable problems).
The point the book is trying to make there is that this snippet would fail to compile:
b.buck();
Because b is of (compile-time) type Animal and Animal doesn't have a buck() method. In other words, Java (like C++), will verify at compile time whether the method call makes any sense, based on the information it has about the type of the variable.
Now the reason the book's results correspond to runtime binding is precisely because you have runtime binding at that call spot: in Java (unlike in C++), all non-static methods are virtual by default.
Thus, there's no need for a virtual keyword that would allow you to explicitly opt in to polymorphism semantics (as you would in C++ and C#, for example). Instead, you can only prevent any further overrides of your methods by individually marking them as final or marking their containing class as final (if the latter is applicable in your case).
#Sandeep - regarding your latest comment (at the time of this writing)...
If in Java, all non-static methods are virtual by default,
why the does the books says "To reiterate, the compiler
looks only at the reference type, not the instance type"?
Isn't this statement amounting to compile time binding?
I think the book is a bit incomplete...
By 'reference type' the book is talking about how a given variable is declared; we can call that the variable's class. One thing that will help you coming from C++ is to think of all Java as variables as pointers to a particular instance (except primitive types like 'int'). It is easy enough to say everything in Java is "pass by value", but because variables are always pointers it is the pointer value that gets pushed onto the stack whenever a method call is made... the object instances themselves stay in the same place on the heap.
This is what I was originally writing before I noticed the comment...
The ideas of "Compile time" and "run time" are not that helpful (for me) for for predicting behavior.
I say that because a more useful question (for me) is "How do I know what method will be called at runtime?"
And by "How do I know" I mean "How do I predict" ?
Java instance methods are driven by whatever the instance actually is (virtual functions in C++).
An instance of Class Horse instance will always be a Horse instance.
The following are three different variables ("reference types" to use the books phrasing) that all happen to refer to the same instance of Horse.
Horse x = new Horse();
Animal y = x;
Object z = x;
Java class methods (basically any method w/'static' in front of it) are less intuitive and are pretty much limited to the exact class they refer to in the source code, which means "bound at compile time."
Consider the test output (below) when reading the following:
I added another variable to your TestAnimals class, and played with the formatting a little...
In main() we now have 3 variables:
Animal a = new Animal();
Animal b = new Horse();
Horse c = new Horse(); // 'c' is a new variable.
I tweaked the output of eat() a little bit.
I also added a class method xyz() to both Animal & Horse.
From the printouts you can see they are all different instances.
On my computer, 'a' points to Animal#42847574 (yours will say Animal#some_number, the actual number will vary from one run to the next).
'a' points to Animal#42847574
'b' points to Horse#63b34ca.
'c' points to Horse#1906bcf8.
So at the beginning of main() we have one 'Animal' instance and two different 'Horse' instances.
The big difference to observe is how .eat() behaves and how .xyz() behaves.
Instance methods like .eat() pay attention to the instance's Class.
It doesn't matter what Class the variable is that is pointing to the instance.
Class methods, on the other hand, always follow however the variable is declared.
In the example below, even though Animal 'b' refers to a Horse instance, b.xyz() invokes Animal.xyz(), not Horse.xyz().
Contrast this with Horse 'c' which does cause c.xyz() to invoke the Horse.xyz() method.
This drove me CRAZY when I was learning Java; in my humble opinion it was a cheap way to save a method lookup at runtime. (And to be fair, in the mid 1990's when Java was being created, maybe it was important to take performance shortcuts like that).
Anyway, may be more clear after I reassign Animal 'a' to the same Horse that 'c':
a = c;
Now a and c point to same instance:
Animal a=Horse#1906bcf8
Horse c=Horse#1906bcf8
Consider the behavior of both Animal 'a' and Horse 'c' at after that.
Instance methods still do whatever the instance actually is.
Class methods still follow however the variable is declared.
=== begin example run of TestAnimals ===
$ ls
Animal.java Horse.java TestAnimals.java
$ javac *.java
$ java TestAnimals
Animal a=Animal#42847574
Animal b=Horse#63b34ca
Horse c=Horse#1906bcf8
calling a.eat(): Hello from Animal.eat()
calling b.eat(): Hello from Horse.eat()
calling c.eat(): Hello from Horse.eat()
calling a.xyz(): Hello from Animal.xyz()
calling b.xyz(): Hello from Animal.xyz()
calling c.xyz(): Hello from Horse.xyz()
Now a and c point to same instance:
Animal a=Horse#1906bcf8
Horse c=Horse#1906bcf8
calling a.eat(): Hello from Horse.eat()
calling c.eat(): Hello from Horse.eat()
calling a.xyz(): Hello from Animal.xyz()
calling c.xyz(): Hello from Horse.xyz()
$
=== end example run of TestAnimals ===
public class TestAnimals {
public static void main( String [] args ) {
Animal a = new Animal( );
Animal b = new Horse( );
Horse c = new Horse( );
System.out.println("Animal a="+a);
System.out.println("Animal b="+b);
System.out.println("Horse c="+c);
System.out.print("calling a.eat(): "); a.eat();
System.out.print("calling b.eat(): "); b.eat();
System.out.print("calling c.eat(): "); c.eat();
System.out.print("calling a.xyz(): "); a.xyz();
System.out.print("calling b.xyz(): "); b.xyz();
System.out.print("calling c.xyz(): "); c.xyz();
a=c;
System.out.println("Now a and c point to same instance: ");
System.out.println("Animal a="+a);
System.out.println("Horse c="+c);
System.out.print("calling a.eat(): "); a.eat();
System.out.print("calling c.eat(): "); c.eat();
System.out.print("calling a.xyz(): "); a.xyz();
System.out.print("calling c.xyz(): "); c.xyz();
}
}
public class Animal {
public void eat() {
System.out.println("Hello from Animal.eat()");
}
static public void xyz() {
System.out.println("Hello from Animal.xyz()");
}
}
class Horse extends Animal {
public void eat() {
System.out.println("Hello from Horse.eat()");
}
static public void xyz() {
System.out.println("Hello from Horse.xyz()");
}
}
This question can be re-phrased as difference between Static binding & Dynamic binding.
Static binding is resolved at compile time and Dynamic binding is resolved at run time.
Static binding uses type of "Class" (reference as per your example) and Dynamic binding uses type of "Object" (instance as per your example). private, final ,static methods are resolved at compile time.
Method overloadingis an example ofStatic binding&Method overridingis example ofDynamic binding`.
In your example,
Animal b = new Horse();
b.eat();
resolution of Object on which "eat()" method has to be invoked happens at runtime for Animal b. During runtime, Animal b has been resolved to Horse type and Horse version of eat() method has been invoked.
Have a look at this article for better understanding.
Have a look at related SE question : Polymorphism vs Overriding vs Overloading

Java - Avoiding cast using an array of superclass-objects

I have many sub-classes implementing the superclass Animal (Dog, Cat, Mouse, etc)
So I do:
Animal[] arrayOfAnimals = new Animal[100];
I put in it Dog,Cat etc objects.
When I get something from it I do
If(arrayOfAnimals[1] instanceof Dog) {
((Dog)(arrayOfAnimals[1])).speak();
}
else if(arrayOfAnimals[1] instanceof Cat) {
((Cat)(arrayOfAnimals[1])).speak();
}
Because I need to know if that Animal is a Cat or a Dog because,for example, each one speaks differently.
Now assuming I have many subclasses of Animals, I will consecutively get many "else if..."
My question is: Is there a way to avoid this? I have already tried using an interface (Animal -> interface, Dog,Cat etc implementing animal), but in my project an array has to be cloneable, and you can't clone an array "Animal [] arrayOfAnimals" if Animal is an interface (objects inside that array will not be cloned)
Because i need to know if that Animal is a Cat or a Dog because,for example, each one speaks differently.
That sounds like it's an implementation detail - if every animal can speak in some form, you should put the speak() method into Animal as an abstract method. Each subclass will then override it to provide the implementation. Then you can just use
arrayOfAnimals[1].speak();
... and polymorphism will take care of using the right implementation.
You can clone an array of an interface type, btw:
interface Foo {
}
class FooImpl implements Foo {
}
public class Test {
public static void main(String[] args) {
Foo[] foos = { new FooImpl() };
Foo[] clone = (Foo[]) foos.clone();
System.out.println(foos[0] == clone[0]); // true
}
}
Note that regardless of the type involved, calling clone() on array won't clone each element - the new array will contain the same references as the old array. It's a shallow copy. If you want to do that, you'll have to code it yourself (or find a third party library).
Why don't you move speak() to the superclass and let the subclasses override it?

When should or shouldn't I use a more general variable type for referencing my object?

There are 2 classes A and B, B extends A. What is the difference between
A a = new B();
and
B b = new B()?
Both create the object of class B. What is the difference?
You are right that in both cases an object of class B is created. The difference between the two declarations is in the type of the variable.
It is very important to keep the distinction between variables and objects in mind. For example, the following code defines 3 variables but only 2 objects:
Circle c1 = new Circle(5);
Circle c2 = c1;
Circle c3 = new Circle(5);
When you say
Shape s = new Circle(5);
instead of
Circle s = new Circle(5);
assuming Circle extends Shape then, even though in both cases you did create a circle object, in the former case you can only call shape methods on the circle (through the variable s) whereas in the second case you can you all circle methods (because you will be calling them through the circle variable c). That is a call like s.getArea() will work in both cases but something like s.getRadius() will ONLY be allowed in the second (unless you use an ugly cast).
So why do we often do things like the first case? That is, why do we often define our variables of a more general type than necessary? Usually we do this because we want to restrict the interface for safety. Perhaps we only care about shapes, but in this case the particular shape just happens to be a circle. If you cared about circle specific properties, then we would have used a circle variable. But we should strive to be as general as possible. Coding to the most general interface allows our code to work with shapes other than circles without modification.
Of course, for this to really sink in, you have to experience it firsthand, but hopefully this explanation is a start. There are many books and blog posts and articles that explain this in more detail with useful real-life anecdotes I'm sure.
A a = new B();
has only the attributes and methods of A.
B b = new B();
has the the attributes and methods of B.
If you added some attributes or methods to B, you can't call them with a.
The advantage is
Fruit f = new Mango();
Suppose
consumeFruit(Fruit f);
now you can call
consumeFruit(new Mango());
consumeFruit(new Strawberry());
Note:
For this case you would be only able to call the methods declared in the reference type. and object type's version will get invoked . and you would be only accessing fields from the reference type's class
See Also
Liskov substitution principle
If you say
List a = new ArrayList();
then you reference ArrayList only in one place in your code. That makes it easier to change it later to something else, like LinkedList;
Of course, this does not work if you need methods specific to ArrayList.
In general, you should use the most general type applicable.
This question is on Polymorphism. Following is an extract from Kathy Siera:
public class TestAnimals {
public static void main (String [] args) {
Animal a = new Animal();
Animal b = new Horse(); //Animal ref, but a Horse object
a.eat(); // Runs the Animal version of eat()
b.eat(); // Runs the Horse version of eat()
}
}
class Animal {
public void eat() {
System.out.println("Generic Animal Eating Generically");
}
}
class Horse extends Animal {
private void eat() { // whoa! - it's private!
System.out.println("Horse eating hay, oats, "
+ "and horse treats");
}
}
If this code compiled (which it doesn't), the following would fail at runtime:
Animal b = new Horse(); // Animal ref, but a Horse
// object , so far so good
b.eat(); // Meltdown at runtime!
Suppose this example:
We have class an animal:
public class Animal {
public void eat() {
// each animal can eat
}
}
Now we have another class dog:
public class Dog extends Animal {
public void bark() {
// dogs can bark
}
}
Now we can write this code:
Animal pet = new Dog();
Now we know, that pet can eat, but nothing more. But if we write
Dog pet = new Dog();
Then we know, that our pet can eat and bark.
Also there is safe and unsafe casting. Safe casting is from Dog to an Animal because each dog is animal (extends it)
Dog pet = new Dog();
Animal animal = pet;
But if we want to cast Animal to Dog we have to test if the instance of animal is really dog, because it doesn't have to be.
Animal pet = new Dog();
Dog myDog = null;
if (pet instanceof Dog) {
myDog = (Dog) pet;
}
Usually, declaring a parent class and assigning it an inherited class is useful when the parent class variable may be assigned different objects. For example
Pet p;
if (favoritePet == Pets.CAT) {
p = new Cat();
} else {
p = new Dog();
}
System.out.println(p.someMethodFromPet());

Categories