Pergunta

Just confused on how to following answer is correct.

class Cat {
    public void isClawedBy(Cat c){
        System.out.println("Clawed by a cat");
    }
}

class Kitten extends Cat{
    public void isClawedBy(Kitten c){
        System.out.println("Clawed by a Kit");
    }
}

If the following is called

Cat g = new Cat();
Cat s = new Kitten();
Kitten t = new Kitten();

g.isClawedBy(t);
s.isClawedBy(t);
t.isClawedBy(t);

How is the answer: Clawed by Cat Clawed by Cat Clawed by Kitten

I'm confused on why s.isClawedBy(t) = Clawed by Cat. Since the dynamic type of s is a kitten, and t is a kitten. Is it because the arguments are different, so it doesn't override it?

Another part I am confused on. //Note the arguments have been swapped.

class Cat {
    public void isClawedBy(Kitten c){
        System.out.println("Clawed by a cat");
    }
}

class Kitten extends Cat{
    public void isClawedBy(Cat c){
        System.out.println("Clawed by a Kit");
    }
}

If the following is called

Cat g = new Cat();
Cat s = new Kitten();
Kitten t = new Kitten();

g.isClawedBy(t);
s.isClawedBy(t);
t.isClawedBy(t);

The output is: Clawed by Cat Clawed by Cat Clawed by Cat

How does it work for when t is called?

Foi útil?

Solução

About the second query : t.isClawedBy(t) giving the output of Clawed by Cat.

Since t is a Kitten and the argument passed in the method t.isClawedBy(t) is also Kitten , the method from the superclass Cat will be called because it matches the arguments perfectly.

Outras dicas

Class Kitten does not override isClawedBy(Cat c). It adds a new method isClawedBy(Kitten c). The runtime sees s referenced as a Cat at the time s.isClawedBy(t) is called, and it ends up calling the Cat method.

If you change Kitten to:

class Kitten extends Cat{
@Override
    public void isClawedBy(Cat c){
    System.out.println("Clawed by a Kit");
    }
}

Then you will see the output you desire. Even more interesting, you can do:

((Kitten) s).isClawedBy(t); and you will see the proper method called.

I'm confused on why s.isClawedBy(t) = Clawed by Cat. Since the dynamic type of s is a kitten, and t is a kitten.

s has reference type Cat but holds a Kitten object. t has reference type Kitten and holds an object Kitten. When the method is run at run-time it is first checked if the reference type has such a method and then the most specific version of the method is called. Since the subclass doesn't override the method (different types in the parameter) the method in the reference type is called.

For your second part it is the exact same thing happening, there is no overload and a Kitten can indeed be passed as a Cat to the method in the reference type so again this method is the most specific one in the hierarchy and it is called.

As for the first question;

Overriding resolution is done at runtime, but overloading resolution is done at compile time.
Since the signature of your methods are not identical (different parameter types. It doesn't matter that one's the subclass of another), they're overloading.

Since resolved at compile time, the compiler does not know what the instance type is; only the declared type.
To the compiler, s.isClawedBy(t) is the method isClawedBy(Kitten) of the declared type Cat.
The compiler says "yep, Cat can accept a Kitten in its method, that's what this method is".
So, at runtime, which method that will call has ALREADY been chosen by the compiler. The lookup is NOT performed at runtime.

Thus, at runtime, despite s actually being a Kitten object, the Cat method is called.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top