I have a subclass ScottishPerson
which inherits from the class BritishPerson
.
class BritishPerson {
public String name = "A british name";
public void salute() {
System.out.println("Good Morning!");
}
}
class ScottishPerson extends BritishPerson {
public String name = "A scottish name "; //Variable overriding
public String clanName = "MacDonald";
public void salute() //Method overriding
{
System.out.println("Madainn Mhath!");
}
public void warcry() {
System.out.println("Alba Gu Brath!");
}
}
class Driver {
public static void main(String[] args) {
ScottishPerson scottishPerson = new ScottishPerson(); //Created as a subclass, can always be upcasted.
BritishPerson britishPerson = new BritishPerson(); //Created as the superclass, throws an error when downcasted.
BritishPerson britishPersonUpcasted =
new ScottishPerson(); //Created as the subclass but automatically upcasted, can be downcasted again.
//Checking the methods and parameters of scottishPerson
scottishPerson.salute();
scottishPerson.warcry();
System.out.println(scottishPerson.name);
System.out.println(scottishPerson.clanName);
//Checking the methods and parameters of britishPerson
britishPerson.salute();
System.out.println(britishPerson.name);
//Checking the methods and parameters of britishPersonUpcasted
britishPersonUpcasted.salute();
System.out.println(britishPersonUpcasted.name);
}
}
Running the code, this is the output.
Madainn Mhath!
Alba Gu Brath!
A scottish name
MacDonald
Good Morning!
A british name
Madainn Mhath!
A british name
This is where the confusion lies. Upcasting ScottishPerson
to BritishPerson
changes the variable name into the one defined un the superclass. Methods and variables that exist only in the subclass such as warcry()
and clanName
are discarded. However, calling method salute()
on the upcasted class still returns the string based on the subclass implementation.
Is it because when I created the object britishPerson
I ONLY initialize the BritishPerson
class, and that when I created the object britishPersonUpcasted
I created both the BritishPerson
class and ScottishPerson
class which lead to the permanent overriding of the salute()
method?
The object on which you are actually calling method belongs to ScottishPerson
so at compile time it check for the reference variable but the runtime it always executes the methods which belongs to the object not to reference which holding it. The runtime polymorphism actually lie behind this concept.
Please have a look at this question for more understanding of upcast and downcast:
What is the difference between up-casting and down-casting with respect to class variable
I also made an example for looking at upcast behavior:
abstract class Animal
{
public void saySomething()
{
System.out.println("Some Animal sound");
}
public abstract void getTheBall();
}
class Horse extends Animal
{
public void saySomething()
{
System.out.println("Neigh Neigh");
}
public void getTheBall()
{
System.out.println("I won't, Try a dog, I am a Horse!");
}
}
class Dog extends Animal
{
public void saySomething()
{
System.out.println("woof woof, waon waon");
}
public void getTheBall()
{
System.out.println("huf huf, here it is!");
}
}
public class Main
{
public static void main (String [] args)
{
Dog dog = new Dog();
Horse horse = new Horse();
Animal animal = dog;
Animal horseAnimal = new Horse();
//upcasting
Dog upcastedAnimal = upcastToDog(animal);
dog.saySomething();
dog.getTheBall();
upcastedAnimal.saySomething();
upcastedAnimal.getTheBall();
horse.saySomething();
horse.getTheBall();
try {
Dog upcastedDog = upcastToDog(horseAnimal);
} catch (Exception ex){
System.out.println(ex.getClass().getSimpleName() + ": Obviously a horse is not a dog!");
}
}
public static Dog upcastToDog(Animal animal){
return (Dog) animal;
}
}
Output:
woof woof, waon waon
huf huf, here it is!
woof woof, waon waon
huf huf, here it is!
Neigh Neigh
I won't, Try a dog, I am a Horse!
ClassCastException: Obviously a horse is not a dog!
First of all java will throw exception if incompatible types are trying to be casted.
In the case when cast is possible, overriden methods will always be called from the actual instance. In your case instance is ScottishPerson so methods will be called on ScottishPerson, even if you hold its reference in a BritishPerson.
you can run the example here https://repl.it/B83f/3
In JLS it is covered here "Narrowing Reference Conversion", as he name suggests only reference is narrowed or widened (or upcasted or downcasted) not the instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With