about downcasting and Polymorphism - java

why do I have to write like this
animal a = new cat();
cat b = (cat)a;
b.makesound();
a.makesound();
but not like this
animal a = new cat();
animal b = new cat();
a.makesound();
b.makesound();
they give the same outputs
This is the entire code.
public class DownCasting
{
public static void main(String args[])
{
animal a = new cat();
cat b = (cat)a;
b.makesound();
a.makesound();
}
}
class animal
{
public void makesound()
{
System.out.println('w');
}
}
class cat extends animal
{
public void makesound()
{
System.out.println("meow");
}
}
so downcasting just give an object second name? or it has other uses?

In the second variant, you create two cats.
In the first, you assign the additional name b to the already existing animal a.
so downcasting just give an object second name? or it has other uses?
You might want to have a list of animals, f.ex. a dog:
class dog extends animal
{
public void makesound()
{
System.out.println("woof");
}
}
could be combined in the same list with cats.

Casting is the process of forcefully making a variable behave as a variable of another type. If a class shares an IS-A or inheritance relationship with another class or interface, their variables can be cast to each other’s type.
public class DownCasting
{
public static void main(String args[])
{
animal a = new cat();
cat b = (cat)a;
b.makesound();
a.makesound();
}
}
class animal
{
public void makesound()
{
System.out.println('w');
}
}
class cat extends animal
{
public void makesound()
{
System.out.println("meow");
}
}
In the line animal a = new cat(); you are using a variable of type Animal to refer an object of type Cat, and a.makesound(); will print "meow" because with inheritance, the instance methods bind at runtime.
However, if you try to do cat b = a; (without casting) the Java Compiler will try to use a variable of type Cat to reference an object of type Animal, and that is not possible (you cannot use a variable of a sub-class to reference (execute) methods from a super-class), so it is necessary cast the variable to indicate to the java compiler that it can be sure that despite a is a variable of type Animal, is actually a Cat.
Let me give you an example to make this more clear:
I have your two classes with some modifications:
class animal
{
public void makesound()
{
System.out.println('w');
}
void sleep(){
System.out.println("ZZZ");
}
}
class cat extends animal
{
public void makesound()
{
System.out.println("meow");
}
void play(){
System.out.println("I´m playing");
}
}
both classes now have a method that the other class does not have.
Now let's use it:
public class DownCasting
{
public static void main(String args[])
{
animal a = new cat();
}
}
If I do a.play(); it will give me a compilation error because Java searchs for the method play() inside the Animal Class and cannot find it... Why java does that? as I already said: "With inheritance, the instance methods bind at runtime", so if I want to call that method I have to cast the a variable... ((Cat)a).play();
But what happen if you try to do it the other way around?
Cat c = new Animal(); //This line will never compile...
So, I can cast it like this in order to make it compile:
Cat c = (Cat)new Animal();
c.play();
BUT, in runtime it will throw a java.lang.ClassCastException why?, because you cannot use a variable of a sub-class to reference (execute) methods from a super-class.
To sum up, remember that the type of the object reference variable and the type of the object being referred to may be different.
But there are rules on how different these can be.
To this topic I will recommend you OCA Java SE 7 Programmer I Certification Guide: Prepare for the 1ZO-803 exam specifically the chapter 6.

why do I have to write like this
to answer this question you need to know first what can make a sound?
the cat or the animal?
you do this :
animal a = new cat();
a.makesound();
when the method makesound is declared in animal
if not then you need to cast

Related

Inheritance not allowing me to create an object of subclass?

class Animal {
String type;
int size;
public Animal(String name, int size)
{
this.type = name;
this.size = size;
}
public Animal ()
{
}
public void run() {
System.out.println("I can run!");
}
}
class Cat extends Animal {
String color;
public void meow() {
System.out.println("I can meow!");
}
}
public class HelloWorld{
public static void main(String []args){
Animal cat = new Cat();
cat.meow();
cat.run();
}
}
Why is it when I try to create a new Cat object from the superclass Animal, I get an error with the .meow() part of the code. Specifically "error: cannot find symbol cat.meow();" . Aren't I creating a Cat object so shouldn't it have access to the methods in there?
Animal is the base class. If you extend Animal you can add additional methods and instance variables in that class, which you actually did correctly.
As soon as you instantiate a child class (class that extends the base class, e.g.: new Cat()) but assign it to the type of the base class (Animal) you can only call the methods that are available there, i.e. in your case you could only call methods that are declared in the Animal class.
Lets assume you have a class Animal :
public class Animal {
public void makeSound() {
System.out.println("Default sound");
}
}
Now you create a class Cat that extends Animal:
public class Cat extends Animal {
private int catProperty = 5;
//Override method of base class
public void makeSound() {
System.out.println("Meow");
}
public int getCatProperty(){
return this.catProperty;
}
}
An another class called Dog that extends Animal:
public class Dog extends Animal {
private int dogProperty = 8;
//Override method of base class
public void makeSound() {
System.out.println("Woof");
}
public int getDogProperty(){
return this.dogProperty;
}
}
Since Animal is the base class you can now create an array of type Animal which holds Cats and Dogs.
Animal[] animals = new Animal[2];
animals[0] = new Cat();
animals[1] = new Dog();
for (Animal animal : animals) {
animal.makeSound();
}
Each of the animals (Cat and Dog) will now print the proper sound.
In case you really need to call a child class specific method, you have to cast the object back to an instance of that child class. In that case you have to be sure of what type the child class is.
E.g.:
for (Animal animal : animals) {
// Calls overriden method
animal.makeSound();
// This is illegal. Method getCatProperty is not declared in Animal
animal.getCatProperty();
// This is illegal. Method getDogProperty is not declared in Animal class
animal.getDogProperty();
/*
* IF YOU HAVE TO CALL CHILD CLASS SPECIFIC METHODS, DO IT LIKE THIS:
*/
// Checks if animal is of type Cat
if (animal instanceof Cat) {
// Casts animal to instance of Cat
Cat cat = (Cat) animal;
// Calls specific Cat instance method
System.out.println(cat.getCatProperty());
}
// Checks if animal is of type Dog
if (animal instanceof Dog) {
// Casts animal to instance of Dog
Dog dog = (Dog) animal;
// Calls specific Dog instance method
System.out.println(dog.getDogProperty());
}
}
Just as a sidenote: If you plan not to directly create instances of Animal (Animal a = new Animal()), you should declare the class itself and the methods that should be overriden by child classes as abstract.
public abstract class Animal {
public abstract void makeSound();
}
Also, in case that base class only has methods and no instance variables that should be available to the child classes, it's probably better use an interface instead of a (abstract) class.
public interface Animal {
public abstract void makeSound();
}
The interface then has to be implemented (not extended) by the concrete class.
public class Cat implements Animal {
public void makeSound() {
System.out.println("Meow");
}
}
Hope this helps!
Animal cat = new Cat()
The compiler "forgets" that you created a Cat instance.
Your sourcecode says: I have a variable named cat that is an instance of Animal.
There is no method meow() on the Animal class.
If you want to call a subclass method, you need a subclass instance:
Cat cat = new Cat();
cat.meow();
or you need to cast. Basically you tell the compiler: "I know better than you".
Animal cat = new Cat();
( (Cat) cat).meow();
The point is: java is statically typed. In python, the interpreter would just see if that cat thingy has a method called meow() that it could call. Doesn't work like that in Java.

Difficulty with the concept of java inheritance and overriding [duplicate]

This question already has answers here:
Why bark method can not be called
(5 answers)
Closed 6 years ago.
The Superclass reference variable can hold the subclass object, but using that variable you can access only the members of the superclass, so to access the members of both classes it is recommended to always create reference variable to the subclass.
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
b.bark();
}
}
output:
TestDog.java:26: error: cannot find symbol
b.bark();
^
symbol: method bark()
location: variable b of type Animal
1 error
What I do not understand here is why is the object 'b' able to access the Dog.move() and not Dog.bark() because the statement mentioned above says it can access only the members of the superclass and not the subclass.Following this logic the output of b.move() should be "Animals can move" and not "Dogs can walk and run".But that is not case.Can anyone help me with this?Thanks in advance!
Congratulations - you just discovered polymorphism.
In Java the classes are bound dynamically. That is if you are invoking a method the implementation of the object is invoked (in your case the Dog) and not the method of the reference type (in your case the Animal).
This allows overwriting methods and replace or fulfill their implementation.
On the other hand, you can only access methods that are available in the type you are referencing, not the implementing type (in your case the Animal). To invoke the methods of the instance, you would have to use it as the reference type (in your case the Dog).
In your question Animal is a parent class which doesn't have bark() method so that method isn't overridden. If you were able to access bark() from parent class without declaring either abstract method or defining it, then that would be violation of the Polymorphism principle.
If you really want to access it that way, then you can either define a abstract public void bark(); in your parent or access that method by typecasting like this
((Dog) b).bark();
This will not compile since Animal does not have a method called bark.
Think of it this way, all dogs are animals, but not all animals are dogs. All dogs bark, but not all animals bark.
This code is wrong, as the line b.bark(); will give you a compiler error, because b is only defined as an Animal, which cannot bark().
If you change Animal b = new Dog(); to Dog d = new Dog(); it will work properly.
You've got inheritance mixed up. Dog can do what Animal can do, not vice versa.
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
#Override public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
public void moveSuper() {
super.move();
}
}
public class TestDog {
public static void main(final String args[]) {
final Animal a = new Animal(); // Animal reference and object
a.move(); // runs the method in Animal class
final Dog d = new Dog(); // Animal reference but Dog object
d.move(); // runs the method in Dog class
d.bark();
d.moveSuper();
}
}

Clarification about overriding in Java

Using this as an example:
class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();// runs the method in Animal class
b.move();//Runs the method in Dog class
}
}
Is it right here to say upon calling b.move() the method "move() under the Dog class" has overridden the "move() under the Animal class" as the Dog object takes precedence when calling the same method when referenced by an Animal type?
Ive noticed many websites don't explain this, rather they just throw out examples without talking through the stuff line by line. Just want to clear up my terminology confusion.
A side note, would it be possible to have a Dog object but invoke move() which is under the Animal class? for example having something like:
Dog doggy = new Dog();
doggy.move()
>>>
Animals can move
>>>
Would this be possible? would ((Animal) doggy).move() accomplish this?
Absolutely, it is correct to say upon calling b.move() the method "move() under the Dog class" has overridden the "move() under the Animal class".
For the second question, you should implement the class Dog as:
public class Dog extends Animal {
public void move(){
super.move();
}
}
For the third question, the answer is "NO".
((Animal) doggy).move()
This is simply 'redundant' and give the output "move() under the Dog class".
You can do it like this
class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
public void moveParent() {
super.move();
}
}
public class Main{
public static void main(String args[]){
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();// runs the method in Animal class
b.move();//Runs the method in Dog class
Dog doggy = new Dog();
doggy.moveParent();
}
}
Use super keyword to call upon the parents member functions or data members.
like: super.move(); in this case you parent function will be called.
From the oracle docs
If two or more independently defined default methods conflict, or a default method conflicts with an abstract method, then the Java compiler produces a compiler error. You must explicitly override the supertype methods.
So basically, if you're in the sub-class calling a method which is in the superclass, you won't be able to call the super-class' method unless you use super.function(). Read up more on it here
It's principle object oriented programming (aka OOP) - polymorphism. Dog, Cat, Elephant are all animal.
Animal d = new Dog();
Animal c = new Cat();
Animal t = new Tiger()
It must not care about, always right. :)

dynamic polymorphism

class Test {
public static void main(String[] args) {
Animal a = new Dog();
Dog d = new Dog();
d.makeNoise(); // output "Sub"
a.makeNoise(); // output "Sub" then what is use of calling this. why not call d.makeNoise() only.
}
}
abstract class Animal {
public void makeNoise() {
System.out.println("Super");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Sub");
}
}
We had 15 minutes discussion over this topic(15 minutes is too long I guess) I explained interviewer about how dynamic polymorphism will be achieved with the help of a.makeNoise(); but still she was saying both are giving same output.
a.makeNoise(); output "Sub" then what is use of calling this. why not call d.makeNoise() only
I went to interface also but still question was if subclass reference is giving same output then why to use superclass reference.
Interviewer question was, what difference a.makeNoise(); makes? why not call d.makeNoise(); only when both are giving same output?
What could be the possible correct answer?
Animal a = new Dog(); // this animal is a dog
Dog d = new Dog(); // this dog is a dog
A dog is a dog, however you declared it.
a.getClass() equals d.getClass() equals Dog.class.
On the other hand:
Animal a = new Animal(); // this animal is an animal
a.makeNoise(); // prints "Super"
The example below illustrates dynamic polymorphism. Both a and d are declared to be Animals, but d is actually a dog.
Notice that when I call makeNoise on the Animal d, java will know that d is actually a dog and not just any animal.
class Test {
public static void main(String[] args) {
Animal a = new Animal();
Animal d = new Dog();
d.makeNoise(); // output "Bark" - d is an animal that barks
a.makeNoise(); // output "Squawk" - a is an animal that squawks
}
}
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
This is the reason-
Animal a = new Dog();
Animal is dog so noise would be same :)
If create another animal, say Cat, with that method, and point animal to Cat, you should get a different noise.
Your simplified example does not present the case well enough.
Collection<Animal> caged = getCagedAnimals();
for (Animal a : caged)
a.makeNoise();
As there are many types of animals (classes), each makes a different noise. We do not need any typecasting to obtain different behavior, so to say. Imagine the horrors which would happen if we would want each animal to make a noise without polymorphism:
for (Animal a : caged) {
if (a instanceof Dog)
((Dog)a).woof(); // or, ((Dog)a).makeNoise()
else if (a instanceof Cat)
((Cat)a).meow(); // or, ((Cat)a).makeNoise()
else {...}
}
Let us have an object of type T. We are trying to invoke toString() (defined by Object class)
Dynamic method invocation proceeds as follows (actually, a virtual method table is used):
C = T
do
if (C defines toString()) {
call T.toString()
break
}
C = superclass of C
while (C != null)
throw new NoSuchMethodError();
Now, if we have
Object obj = new T();
and we call
obj.toString();
we are actually calling toString() of class T.
consider there are 3 classes
animal
dog
cat
cat and dog are sub classes of animal.
class Test {
public static void main(String[] args) {
Animal a = new Animal();
int user_input=userinput(); //returns 1 for cat and 2for dog
switch(user_input)
{
case 1:Animal d=new Cat();
break;
case 2: Animal d=new Dog();
break;
}
d.makeNoise(); // output "Bark"/"meow" as per user input(dynamic linking)
a.makeNoise(); // output "Squawk" - a is an animal that squawks
}
}
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Cat extends Animal {
#Override
public void makeNoise() {
System.out.println("meow");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
class Account {
public static void main(String[] args) {
Animal a = new Dog();
Dog d = new Dog();
d.makeNoise();
a.makeNoise();
a = new Cat();
a.makeNoise();
}
}
abstract class Animal {
public void makeNoise() {
System.out.println("Super");
}
}
class Dog extends Animal {
public void makeNoise() {
System.out.println("Sub");
}
}
class Cat extends Animal {
}
See the above modified example and the observations
We have an abstract class Animal with an implementation for makeNoise (let me say default implementation here)
We have a Dog class which is of Type animal but has a customized makeNoise methods
We have a Cat Class which is of Type animal but has no customized makeNoise methods. it uses default makeNoise of Animal type.
if I use Animal a = new Dog() and a.makeNoise(), then I can remove my makenoise method from Dog class whenever I wish with no changes to any other class. It will still compile and execute without any error.
if I use Dog d = new Dog() and d.makeNoise(), then I cannot remove my makenoise method from Dog class whenever I wish. if I do, I also need to change the main class for the application to compile.
i will give one general ex:- personA has one bank account he has all permissions on that account(withdraw,deposit,loanetc). personB wants to deposit money into personA account in this time he wants to access personA's account but we have to provide deposit permissions only.
class perosnB
{
public void deposit()
{
................
}
}
class personA extends personB
{
public void deposit()
{
......
}
public void withdraw()
{
......
}
}
personA p=new personB();
PersonB p2=new personB();
by using p object we can access only withdraw method. by using p2 we can access deposit also.
weather personA class is abstract or not. if personA is abstract class creating object for personA class is not possible( personA p=new personA()) . personA p=new personB() is possible.
Animal a = new Dog();
a is a a reference of type Animal but it refers to the object of type Dog.
Here Dog overrides makeNoise() method of Animal class.
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
Since object is of Dog class JVM will bind Dog class' makeNoise() method to the object and binding will be done at runtime.
so the Output of
a.makeNoise();
will be
sub

Java object reference mechanisms

I'm kind of stuck on the following question:
What two Java language mechanisms allow the type of an object reference variable to be "different" than the type of the object to which it refers? Give specific examples to illustrate. In what sense are they not different at all?
My current answer is that it is "implement" and "extend" right? And they are similar because they both will make a class that at least will posses all of the method signatures of the super class which can be actual, abstract, or an interface. Is this correct? Thanks in advance!
That is more or less correct. The second part of your answer should talk about subtyping. In Java, it is not sufficient for objects to just have the same method signatures. There actually has to be a declared subtyping relationship (via extends / implements).
This is not mere pedantry. In some languages (but not Java), the mere existence of compatible method signatures is sufficient for type compatibility. This is called "duck typing".
Implements
interface Animal {
void attackHuman(); // actually public abstract by default
}
class Horse implements Animal {
public void attackHuman() { }; // must implement
}
// type and reference the same
Horse a1 = new Horse();
// type and reference different
Animal a2 = a1;
Extends
class Animal {
void attackHuman();
}
class Dinosaur extends Animal {
// attackHuman() inherited
}
// type and reference the same
Dinosaur a1 = new Dinosaur();
// type and reference different
Animal a2 = a1;
See this example....
- Here the Animal is the Super-Class, and the Dog and Cat are inherited out of it.
- You can Create a Dog object using an Animal Object Reference Variable.
- This is known as Class Polymorphism.
public class Test {
public static void main(String[] args){
Animal a = new Dog();
new Hospital().treatAnimal(a);
}
}
class Animal {
public void sayIt(){
}
}
class Dog extends Animal{
public void sayIt(){
System.out.println("I am Dog");
}
}
class Cat extends Animal{
public void sayIt(){
System.out.println("I am Cat");
}
}
See the NEXT PAGE for the Remaining Code
class Hospital{
public void treatAnimal(Animal a){
if(a instanceof Dog){
a.sayIt(); // Will output "I am Dog"
}
else{
a.sayIt(); // Will output "I am Cat"
}
}
}

Categories

Resources