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.
Advertisement
Answer
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.