2

I have the following classes :

public abstract class Animal
{
    private String species;
    public Animal(String ll)
    {
        species = ll;
    }

    public abstract void speak();

    public String toString()
    {
        return "Species: " + species;
    }

}  

The 2nd class:

public class Raven extends Animal
{
    String name;
    public Raven(String emri)
    {
        super("Raven");
        name = emri;
    }

    public void speak()
    {
        System.out.println("krra krra");
    }

    public String toString()
    {
        return super.toString() + "\nName : "+ name ;
    }

}

and the test class :

public class TestAnimals
{
    public static void main(String args[])
    {
        Raven blabla = new Raven("Ziosh");
        Animal a = blabla;

        System.out.println(a.toString());
    }
}  

When I execute the test class, I get :

Species: Raven
Name: Ziosh

What I don't understand is why does Java use the "new" toString() method, even after we "upcast" the Raven object to Animal ? Thanks.

Kalyan Vedala
  • 1,049
  • 2
  • 17
  • 33
Kushtrim
  • 45
  • 6
  • 1
    First, you `DOWN`cast the object. Second, thats because you originally created the `Raven` object, you created a reference to it. – sybear Jul 02 '14 at 18:53
  • `blabla` and `a` are *references*, not objects. When you cast the *reference* to the object, you don't alter the object and the same method is called. – Peter Lawrey Jul 02 '14 at 19:01

4 Answers4

7

Because that's what polymorphism is all about: you can call a method of an object without knowing the actual concrete type of the object, and the appropriate method, defined in this concrete type, will be called.

This works exactly like real objects: if I give you a car, even if you don't know it's actually a hybrid car, the car will behave like a hybrid car when you drive it.

In your example, a and blabla are two references to the same object, which is a Raven instance. So this object *speak*s and *toString*s like a Raven.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
3

When you call a method in java, even if it's cast to the super type, it always looks for the most overridden method to call.

From http://docs.oracle.com/javase/tutorial/java/IandI/override.html

The distinction between hiding a static method and overriding an instance method has important implications:

  • The version of the overridden instance method that gets invoked is the one in the subclass.
  • The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Community
  • 1
  • 1
Strikeskids
  • 3,932
  • 13
  • 27
1
Raven blabla = new Raven("Ziosh");
Animal a = blabla;

Here, a and blabla reference the exact same object, as you can confirm with:

System.out.println(a == blabla);
// prints "true"

As such, a is really a Raven, so naturally it will talk like a Raven, even if you label it an Animal.

Consider another explanation in human terms. Letting the implementation to be executed on an object of a subclass could be actually very dangerous. Imagine a Bicycle class, and its more specialized BicycleWithLittleWheels. The thing about the latter, the little wheels are quite fragile, and if you try to ride it too fast, they could break. If you let somebody ride that bicycle as if was a regular bicycle, completely obvious of the little wheels, he may break it. By similar logic, you probably shouldn't use a high-precision dental drill the same way as a sledgehammer.

This is why, intuitively, you shouldn't let a specialized object be treated as its more general form. Sure, in some cases, it may make sense to use a specialized object as if it was something more general, but not always. How could the compiler distinguish the safe cases from the unsafe cases? That would be too difficult. So to stay on the safe side, the language won't let you do this.

janos
  • 120,954
  • 29
  • 226
  • 236
0

Java always uses the method of the instance as describe in this post: java override method invocation

Community
  • 1
  • 1
succcubbus
  • 874
  • 1
  • 7
  • 24