how to cast up to super class when there is an override function in the sub class
Because you're overriding the method in a subclass, you're getting dynamic dispatch. The method implementation to call will be based on the dynamic type of the instance that it's called on. Upcasting a Jaguar
to a Car
only changes the static type of the instance – the dynamic type is still a Jaguar
, for that's the type of instance you created.
Therefore upcasting has no bearing whatsoever on the dynamic dispatch of a method – nor should it, as the whole point of dynamic dispatch is to ensure that the correct method implementation for the given instance is called no matter what it's statically typed as.
The kind of behaviour you're expecting is static dispatch – the compiler chooses the implementation to call based on the static type of the instance. This is commonly achieved by overloading (rather than overriding) functions.
For example, an overloaded static
method:
class Car {
static func info(for car: Car) {
print("You've got a Car")
}
}
class Jaguar : Car {
static func info(for jaguar: Jaguar) {
print("You've got a Jaguar")
}
}
let jaguar = Jaguar()
Jaguar.info(for: jaguar) // You've got a Jaguar
Car.info(for: jaguar) // You've got a Car
let car = jaguar as Car
Jaguar.info(for: car) // You've got a Car
Here, the compiler resolves which implementation of info(for:)
to call based on the static types of what it's being called on and the arguments being passed. If it's either called on Car
, or the argument passed is statically typed as a Car
, only Car
's overload can possibly be statically dispatched to.
Another example of static dispatch is with a protocol extension, where the method isn't a protocol requirement (as making it a requirement gives it dynamic dispatch).
protocol Car {}
extension Car {
func info() {
print("You've got a Car")
}
}
class Jaguar : Car {
func info() {
print("You've got a Jaguar")
}
}
let jaguar = Jaguar()
jaguar.info() // You've got a Jaguar
let car = jaguar as Car
car.info() // You've got a Car
Here, the compiler resolves which implementation of info()
to call solely based on the static type of the instance that it's called on.
Casting to Superclass, and Calling Overriden Method
Casting is solely for the benefit of the compiler. The JVM doesn't know anything about it, and it does not affect what method gets called. The JVM tries to resolve a method by looking for something that matches the given signature, starting with the most specific class and working its way up the hierarchy towards the root (java.lang.Object) until it finds something.
The purpose of polymorphism is so code calling some object doesn't have to know exactly what subclass is being used, the object being called takes care of its own specialized functionality. Having a subclass override a method means that objects of that subclass need to handle that method in their own particular way, and the caller doesn't have to care about it.
Casting is for odd edge cases where your code can't know what type something is. You shouldn't need to cast if you know the super type (Parent in your example), the subclass should take care of itself.
why overridden method calling from Subclass if i have done up-casting?
When using inheritance, the compile-time type of the reference to an object on which you call a method is only used to see (at compile time) if the method may be invoked.
But at the invocation time, it does not matter what that compile-time type is. What really matters in this case is the runtime type of the object. It is Test
, so the method is searched on Test
first.
For methodOne()
it is a bit different: it is not overriden by Test
, so the version from its superclass (Example
) is invoked.
explicit casting from super class to subclass
By using a cast you're essentially telling the compiler "trust me. I'm a professional, I know what I'm doing and I know that although you can't guarantee it, I'm telling you that this animal
variable is definitely going to be a dog."
Since the animal isn't actually a dog (it's an animal, you could do Animal animal = new Dog();
and it'd be a dog) the VM throws an exception at runtime because you've violated that trust (you told the compiler everything would be ok and it's not!)
The compiler is a bit smarter than just blindly accepting everything, if you try and cast objects in different inheritence hierarchies (cast a Dog to a String for example) then the compiler will throw it back at you because it knows that could never possibly work.
Because you're essentially just stopping the compiler from complaining, every time you cast it's important to check that you won't cause a ClassCastException
by using instanceof
in an if statement (or something to that effect.)
How to cast subclass object to superclass object
A superclass cannot know subclasses methods.
Think about it this way:
You have a superclass
Pet
You have two subclasses of
Pet
, namely:Cat
,Dog
- Both subclasses would share equal traits, such as
speak
- The
Pet
superclass is aware of these, as allPet
s can speak (even if it doesn't know the exact mechanics of this operation) - A
Dog
however can do things that a cat cannot, i.e.eatHomework
- If we were to cast a
Dog
to aPet
, the observers of the application would not be aware that thePet
is in fact aDog
(even if we know this as the implementers) - Considering this, it would not make sense to call
eatHomework
of aPet
You could solve your problem by telling the program that you know sup
is of type subclass
public class Testing
{
public static void main(String args[])
{
subclass sub = new subclass();
superclass sup = (superclass) sub;
subclass theSub = (subclass) sup;
theSub.displaySub();
}
}
You could solve the problem altogether by doing something like this:
public class superclass
{
public void display()
}
System.out.println("Display Superclass");
}
}
public class subclass extends superclass
{
public void display()
{
System.out.println("Display Subclass");
}
}
public class Testing
{
public static void main(String args[])
{
subclass sub = new subclass();
superclass sup = (superclass) sub;
sup.display();
}
}
check out this tutorial on more info: overrides
How does Superclass cast on objects work?
- You are casting a subclass to a superclass.
This is upcasting (or implicit casting) as per: Inheritance -> Casting Obects
This means that this casting can be done implicitly.
You do not have to put casting operator after the assignment.
EveryGrad
object is implicitly an object of classUpgrad
because
of your declaration:Grad extends Upgrad
.
I.e. this will work:
Upgrad u = g;
You have overriden the
perYear()
method.
After casting to a superclass and calling this method it will stay as implemented inGrad
class because of polymorphism principles and override rules for Java:
This questions has in fact been answered here and here on Stackoverflow.
To quote Learning Java by Daniel Leuck & Patrick Niemeyer:When there are multiple implementations of a method in the inheritance hierarchy of an object, the one in the “most derived” class (the furthest down the hierarchy) always overrides the others, even if we refer to the object through a reference of one of the superclass types.
This is defferent from hiding a field.
Hiding or shadowing a field is best described here:
Subclassing and inheritance -> Shadowed Variables
A different set of types is used there in the link but the meaning is the same:Another important point about shadowed variables has to do with how they work when we refer to an object by way of a less derived type (a parent type). For example, we can refer to a DecimalCalculator object as an IntegerCalculator by using it via a variable of type IntegerCalculator. If we do so and then access the variable sum, we get the integer variable, not the decimal one:
DecimalCalculator dc = new DecimalCalculator();
IntegerCalculator ic = dc;
int s = ic.sum; // accesses IntegerCalculator sum
As said in Inheritance -> What You Can Do in a Subclass :
You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).
Testing code:
class Ugrad {
int DM = 140;
int perYear() { return DM/4; }
}
class Grad extends Ugrad {
int DM = 28; // we have *hidden* Upgrad.DM field by
int perYear() { return DM/2; }
}
public class UpgradGrad {
public static void main(String[] args){
Grad g = new Grad();
System.out.println(g.DM); // Grad.DM field is accessed directly, thus output = 28
System.out.println(g.perYear()); // 14
Ugrad u = g; // this will work because of implicit casting to a superclass
System.out.println(u.DM); // g is casted to u. Grad.DM was hiding Upgrad.DM. Thus Upgrad.DM emerges.
System.out.println(u.perYear()); // because g is just referred to as Upgrad, its original Grad.perYear() method will be called
}
}
Related Topics
Switching a @State Property to a @Binding Property Interferes with Animation
Adding Animation to Tabviews in Swiftui When Switching Between Tabs
Changing Tab Bar Color (Swift)
Repeating Action Continuously in Swiftui
How to Change the Colour of Separator in List of Swiftui
Skspritenode Gets Hidden Below Parent Node
Is Gamescene.Sks Not Recommended for Game Building
Check If a Character Is Lowercase or Uppercase
Rotating Uitextview Programmatically
How to Decode the Body of an Error in Alamofire 5
Swift Build Time Too Long When the Configuration Is 'Release'
Can Somebody Post a Good Example of MVC Pattern in Swift
How to Build a Swift Executable for Linux on Macos
How to Use Multiple Mtlrenderpipelinestates in One Mtlrendercommandencoder
Saving Coredata to a Web Server with Swift 3.0
In Swift, Why Can't I Instantiate a Protocol When It Has an Initialiser