So I am having some confusion understanding dynamic binding vs upcasting.
My original understanding was that when you create a base_class
reference and assign it to a derived class object like:
base_class obj = new derived_class();
you can now call the methods/member functions of derived_class
with obj.method_of_derived class()
, without dynamic binding.
I thought you only needed dynamic binding when the base_class
and derived_class
have functions/methods that have the same name, and some sort of overriding needs to happen during the compile time to assign them correctly.
Am I totally wrong?
or is there another reason the below code doesn't work?
public class Ticket {
protected String flightNo;
public Ticket(){
this.flightNo = new String();
}
public void setTicket(lnode ticket){
this.flightNo= ticket.getFlightNumber();
}
public void displayTicket(){
System.out.println("Flight number: " + this.flightNo);
}
}
And a derived class extended from the above class
public class originalTicket extends Ticket {
protected boolean catchAnotherFlight;
protected boolean baggageTransfer;
public originalTicket(){
catchAnotherFlight = false;
baggageTransfer = false;
}
public void setoriginalTicket(lnode ticket){
setTicket(ticket);
}
}
and I am unable to do this:
Ticket object = new originalTicket();
object.setoriginalTicket();//Can't call the originalTicket method.
I have written some programs using upcasting in C++ but I always used dynamic binding. I was just trying to pick up Java and now I am a little startled that I got all the concepts wrong all along. Thanks.
Let me try to explain using more layman terms:
public abstract class Animal {
public abstract void move();
}
public class Cat extends Animal {
@Override public void move() {
moveWithLegs();
}
public void moveWithLegs() {
// Implementation
}
}
public class Fish extends Animal {
@Override public void move() {
moveBySwimming();
}
public void moveBySwimming() {
// Implementation
}
}
Animal animal = new Cat();
animal.move(); // Okay
animal.moveWithLegs(); // Not okay
((Cat) animal).moveWithLegs(); // Okay
((Fish) animal).moveWithLegs(); // ClassCastException exception
The object animal
is just an object reference to anything that is an animal. Even though the actual instance type is Cat
, the compiler would simply treat it as if it is an Animal
.
Therefore, at compile time, you are only allowed to invoke methods defined by Animal
class.
If you know animal
is an instance of Cat
, and you would want to call a method in Cat
class, you need to cast this. By casting, you are telling the compiler, "Hey I know this thing is a cat, I want you to treat this like a cat."
Therefore, by casting, you get the access to the methods in Cat
class, which also includes all members inherited from Animal
class.
If you are not sure if animal
is a Cat
or Fish
, and yet you still cast and call moveWithLegs()
, you would get a ClassCastException
at runtime, which means you broke the contract that you agreed on at compile time.