Suppose I have the following classes
Class Parent{
public void test(){
System.out.println("Parent");
}
}
Class Child extends Parent{
public void test(){
System.out.println("Child");
}
}
Parent parentE = new Child();
parentE.test();
((Parent)parentE).test();
Output is:
Child
Child
But how can I run parent method in this case using parentE reference?
When you override the parent method, the child object will always call the overriding method (child method) due to Polymorphism.
So in your case either you call the parent method explicitly, inside the child object:
Class Child extends Parent{
public void test(){
super.test();
}
}
Or make a Parent object and call it's method.
Parent parentE = new Parent();
parentE.test();
This is a key feature of polymorphism.
The object you instantiated is an instance of Child. Calling that object's test() is always going to result in the Child's (overridden) test() being called, even if you've assigned that instance to a variable of Parent type.
In short, this is how you can achieve more specific behavior while only having to reference the object using a variable declared a superclass type. Often this is used in conjunction with the base class only providing an abstract method for the subclasses to override.
A trivial example in beginner's books usually involves animals or cars:
public abstract class Animal
{
private final String name;
public Animal(String name)
{
this.name = name;
}
public void printName()
{
System.out.println(name);
}
// more animal general stuff followed by:
public abstract void makeSound();
}
public class Dog extends Animal
{
public Dog()
{
super("Dog");
}
#Override
public void makeSound()
{
System.out.println("Woof!");
}
}
List<Animal> aList = new ArrayList<Animal>();
aList.add(new Dog());
aList.add(new Cat());
// etc
for (Animal a : aList)
{
a.printName();
a.makeSound(); // calls each subclasses' "makeSound()"
}
You can't call the Parent's test() unless you instantiate a Parent or call super.test() from within a method in Child.
(I was actually thinking I could find a good duplicate for this that provided a decent answer, but I couldn't)
Simple
Parent parentE = new Parent();
parentE.test();
In case of method overriding that is resolved at run-time based on actual data type of object not on the basis of referee data type.
You can't call call super class's overridden method directly.
Basically, no, you can't do this, and it would be a bad idea. If Child decides that it needs to override one of its inherited methods, then the outside program shouldn't try to subvert that. It's as though the author of the outside module peeked into the implementation of the methods in Parent and Child and decided "I want the Parent version, not the Child version". But that isn't what OOP is all about. The writer of the outside program should not be concerned with how the method is implemented. See Jon Skeet's answer here, which I think explains this as well as anything I've found.
If you find that you really need to do this, then you have a design issue. The solution is going to depend on your particular project (your original code isn't a real-world example so there's no way to answer it for that). But in some cases, the solution might be that the classes need to provide two different methods that have similar but slightly different purposes. And it may be that in some subclasses of your class, the two methods would have the exact same implementation, but in other subclasses they would be different.
I think you mixed two concepts over here. casting and polymorphism. Read about these concept then things will be more clear for you.
Related
Say I have the following classes
public abstract class Parent {
public Parent() {
//stuff here
}
}
public class Child extends Parent {
public Child() {
//stuff here
}
public void doSomething() {
}
}
Then I get an object from an array of Parents
public Parent[] parents = new Parent[5];
Parent tempParent = parents[0]
If this object is of the child class, I want to cast the tempParent into the child class in order to use "doSomething" without having to create a new object
if(tempParent.getClass == Child.class) {
tempParent = (Child) tempParent;
tempParent.doSomething();
}
This, however, does not work. I still get an error telling me that doSomething is not a function in the Parent class. Is there a way to do what I'm trying to do?
You need to use the correct TYPE on the LEFT hand side:
Child someChild = (Child) tempParent;
Note: this does not create a new Object.
There is no way of having
Parent whatever = (Child) tempParent;
do what you want to do (invoke a Child class method)!
You see, the compiler only cares about the "defined" type of your reference, it does not take into account that you most likely, at runtime, just "put" something into that reference that in deed is a Child instance!
to do what you want to do.
And note: do not compare objects using ==. You should prefer to call equals() instead. For Class objects == should work (most of the time), but still: get used to check for equality using equals().
I think you're trying to solve the issue from the wrong side.
Technically speaking you should do it like this.
public abstract class Parent {
public Parent() {
//stuff here
}
public abstract void doSomething();
}
public class Child extends Parent {
public Child() {
//stuff here
}
#Override
public void doSomething() {
// Write the code of doSomething specific to child.
}
}
A bit off topic but you might want to consider the following:
I think that the class representation of your code is bad.
I think that you should have 2 concrete classes Parent and Child that are composed or either inherit from a common interface. Even better use composition over inheritance.
https://en.wikipedia.org/wiki/Composition_over_inheritance
if you are able to modify the parent class, I would recommend that you make doSomething an abstract method and have the child class override it. that way, there is no need to cast in order to invoke it.
https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
In dynamic method binding a superclass reference can only call a subclass method which is inherited and overrode by it. However, the otherwise can be implemented.
abstract class in
{
abstract void print();
}
class a extends in
{
String name=this.getClass().getSimpleName();
void show()
{
System.out.println("class "+name);
}
void print()
{
show();
}
}
class Main
{
public static void main(String args[])
{
in x;
x = new a();
x.print();
}
}
Here, it prints successfully
class a
Also getClass() returns the subclass name instead of superclass name as this refers to the superclass object in main method.
A parent object reference is just constrained by the methods that it has in its class definition. If those methods are overridden by subclass, and at run time, if the actual object referred by the parent reference is of subclass type, then that overridden method is invoked. It doesn't matter if the overridden method invokes methods that are not originally present in the parent class or accesses the variables that are not present in the parent class.
This is what polymorphism is all about. It is by design meant to be this way as it makes program extension easier in case if we have different specific inheritance hierarchies where the parent class need not know the exact implementation of certain methods and can make things implemented by the subclasses as some sort of contract.
Future is unknown A developer writing a class A.java today can never predict in future the names or signatures of the methods which any other developer may include in his class extending A.java. Also such classes may be numerous with each having separate methods.
Base class should never be coupled with its sub classes. It must not care about how the sub classes are implemented.
Although it is not recommended but still if you wish to invoke the method defined in one of the sub class you may do it by typecasting like below.
public class Parent {
public class someMethod(){
if( this instanceof Child1){
((Child1)this).someAdditionalMethod();
}
}
}
public class Child1 extends Parent{
public class someAdditionalMethod(){
}
}
I have done some research but I am no able to find why runtime polymorphism is not taking place in example below.
According to my understanding foo(int a) should have been called in child.But out put is "Parent with long".Can someone throw light on this?
class Parent {
public void foo() throws RuntimeException {
System.out.println("Parent with no Parameter");
}
public void foo(long a) {
System.out.println("Parent with long");
}
}
class Child extends Parent {
public void foo() {
System.out.println("Child with no parameter");
}
public void foo(int a) throws RuntimeException {
System.out.println("Child with int");
}
}
class Demo {
public static void main(String... args) {
Parent p = new Child();
int a = 10;
p.foo(a);
}
}
Output:
Parent with long
Polymorphism only applies when methods have the exact same signature (same number and types of parameters).
What you have is Parent with 2 methods: foo(long) and foo(). And Child that inherits from its parent and add two new different methods: foo(int) and (that one overloads existing methods) foo()(that one overrides the inherited one).
There is different mechanisms: what happens at compile time, and what happens at runtime. At compile time, the compiler will only look accordingly to variable types. At runtime, the execution env. will look at object types.
Now when compiling the call p.foo(a), compiler will look at the type of p, which is Parent and look in Parent class for a corresponding callable method. It finds foo(long) and then generates a dynamic call to a method foo(long) with a cast from int to long to the real object at runtime (of type Child). But this object has only one such method, the one in Parent, so this one will be called.
Change Child's foo(int) into foo(long) and you will have what you wanted.
As you said polymorphism is correct. What you seeing is compile time polymorphism which is overloading.
The method from Child already been decided at compile time cause there is no equivalent method define in parent and no ovveriding (runtime polymorphism) applied .
In java polymorphism works in down to top mechanism.. you see.. when you are creating the child object, you are actuality creating a patent object.. and it will never give an error as your child extends to patent. So.. you are actually creating a patent object.. not a child object at all.. that's why it's executing parents' method.. if you would like to see how polymorphism works.. then just create Child object =new Child ().
And then pass Long or int variable..
Hope that helps
Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
Assume
public class Parent{
public void method() {
}
}
So
public class Child extends Parent {
public void someMethod() {
super.method();
}
}
or
public class Child extends Parent {
public void someMethod() {
method();
}
}
Thanks for your input.
Calling super tells the JVM to explicitly look to the parent class' version of a method. Continuing with your example, if you just call
method()
The JVM will first search in the calling class for the method (in this case Child) before looking at the parent class. On the other hand, if you call
super.method()
then the JVM will explicitly look at the parent class for an implementation, even if Child has an method called method().
Putting these two ideas together, you should probably always use super when you intend to call the parent class' method. If your class does not override the method, then you could call without super. But even this becomes problematical if someone were to refactor your class later on and override the method.
The leading question is easy to answer:
Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
No, its not common practice. On the contrary, its dangerously confusing to do so. You call methods normally, because the main point of inheritance is to allow the classes to override methods to change/extend their behavior. You normally don't care about at which level a method is actually implemented.
The obvious exception is when you do override the method yourself and you want/need the parents functionality.
Now to the dangerously confusing part of explicitly calling super:
public class CallSuper {
static class Parent {
public void foo() {
System.out.println("Parent.foo");
}
/**
* Calls foo to do the main work
*/
public void bar() {
System.out.print
foo();
}
}
static class Child extends Parent {
public void foo() {
System.out.println("Child.foo");
}
public void bar() {
super.foo();
}
}
static class GrandChild extends Child {
public void foo() {
System.out.println("GrandChild.foo");
}
}
public static void main(String[] args) {
Parent p = new Parent();
Parent c = new Child();
Parent g = new GrandChild();
System.out.print("Parent.foo() = ");
p.foo();
System.out.print("Child.foo() = ");
c.foo();
System.out.print("GrandChild.foo() = ");
g.foo();
System.out.print("Parent.bar() = ");
p.bar();
System.out.print("Child.bar() = ");
c.bar();
System.out.print("GrandChild.bar() = ");
g.bar();
}
}
If you run this example it will output (added line numbers for clarity):
1 Parent.foo() = Parent.foo
2 Child.foo() = Child.foo
3 GrandChild.foo() = GrandChild.foo
4 Parent.bar() = Parent.foo
5 Child.bar() = Parent.foo
6 GrandChild.bar() = Parent.foo
The first four lines are not surprising, we get what foo implements at each level, respectively Parents's bar calling its foo. It starts to get odd at line 5. Child bypasses its own override of foo by calling super.bar(), so while its foo() is specialized, bar() is not. In Line 6, you see that GrandChild inherits this oddity from Child, so the somewhat innocent looking super.foo() in Child's bar has now broken GrandChild's expectations that its override of foo() is effective for all bar() as well.
Now if you imagine foo() and bar() actually doing something useful and that they have a meaningful relationship with each other, e.g. you are led to believe (either by Parent's documentation or just common sense) that overriding foo() will change the behavior of bar(), too. Child's "super" is breaking that.
As a rule of thumb, if you see a "super.x()" call anywhere outside of an actual override of "x()", its probably an accident lurking to happen.
Is it common practice to always use super for calling methods out of the superclass? Or is it redundant code?
It's not redundant. It have a special purpose of invoking parent class method (though you ovveriden). When you don't want, don't invoke. If you current class is not child of that class, super won't work for you.
Also if you call an overridden supermethod, does it use the supermethod or the lowest method?(in the inheritance tree)
The overridden method. Since you overridden it in your class.
If you're not overriding, let's talk about performance.
If you call an inherited method in your class, let's say, methodInSuperclass(), the JVM will look for that method first in your class, then up the class hierarchy until it finds it.
Using super.methodInSuperclass() tells the JVM to go directly to the superclass to look for that method.
So, using the super keyword improves performance by a few mills. It's ugly code, but it's not redundant as it will bring some performance improvement.
Consider using it if time is critical.
Calling the super method or not depends entirely on what you are trying to do. If you want to do what the parent class did plus some additional action, then calling the super method is good. If you're doing something completely different in the child implementation then do not call the super method. When you do call the super method in a hierarchy of classes, it calls the one closest to your child class in the hierarchy.
In some cases you may have an API where calling the super method is part of the overall contract. The clone method is such a case.
If Child is having the same version method with Parent, JVM will call the Child's version instead of Parent's version if without "super". The "super" keyword is helpful if you want to make sure the Child is always calling the Parent's version method.
I am familiar with type casting in inheritance model.
Let SuperClass and SubClass be parent and child classes;
SuperClass superClass = new SubClass(); -- Here the object instantiated is a subclass object;
but its reference type is SuperClass; that is only those methods of SuperClass can be called on the subclass object; Any methods that are not inherited/overridden in subclass cannot be called (that is any unique methods of subclass).
I observed same behavior as above if SuperClass is an interface and SubClass implements it. That is only those methods declared in SuperClass interface are available to be called on the SubClass object. Is my understanding correct? But with some casting, I can call methods that is not part of the interface, which I have observed in my sample code below;
I have made some comments on my understanding as how it works;
but I would like to know if that make sense or if my interpretation is wrong;
class Animals {
public void bark(){
System.out.println("animal is barking");
}
}
interface catIF {
public void catting();
}
interface dogIF {
public void dogging();
}
class Dog extends Animals implements dogIF {
public void bark(){
System.out.println("dog is barking");
}
public void dogging() {
System.out.println("dogging");
}
}
class Cat extends Animals implements catIF {
public void bark(){
System.out.println("cat is barking");
}
public void catting() {
System.out.println("catting");
}
}
public class Animal {
public static void main(String[] args){
dogIF dog = new Dog();
//dog.bark(); this fails
//This method actually actually exists;
//but it is not available or hidden because dogIF reference
//limits its availability; (this is similar to inheritance)
Dog dog2 = new Dog();
dog2.bark();
////prints dog is barking
Animals an =(Animals) dog;
an.bark();
//prints dog is barking
//by casting we mean, treat the dog as an animals reference
//but the object itself is a dog.
//call the bark() method of dog
//but dog did not have this method in the beginning (see first line
// in main - when instantiated with interface type)
}
}
Inheritance of interfaces really isn't "flaky" or complicated. They behave exactly the way abstract classes do, with the exceptions that you reference them differently (implements rather than extends) and that you're allowed to inherit as many interfaces as you like but can only have one superclass (abstract or not).
As with other inheritance: If all you know about an object is that it implements an interface, then you can only access it through that interface. If you know that it implements another interface, or a specific superclass, or is an instance of a particular class, then you can cast it to those and access it through the exposed members of those.
So, yes: If all your program knows is that the object is an instance of Animals, then all you can do is call what's declared on Animals. That means bark() plus whatever methods it inherits from Object (since everything is an Object directly or indirectly even if that isn't explicitly stated).
If your program knows that the object is an implementation of dogIF or catIF -- because the variable type says it is, or because you've successfully typecast it to one of those interfaces -- you can also call the method(s) declared by those interfaces. By the way, the usual convention for interfaces is to name them like classes, with UppercasedFirstLetter... since in many cases the difference between an interface and a class really isn't significant to the folks using it.
If your program happens to know that the object is a Dog, you can call anything it inherits from either Animals or dogIF, or that is provided directly by Dog. Of course it could actually be a Chihuahua (subclass of dog), but that's OK, the subclass will respond to anything the superclass would have responded to, in "the right way to maintain the semantics". (That is, a Chihuahua may respond to bark() by saying "yip yip yip grr yip!", but that method really shouldn't cause it to try to bite your ankle.)
Hope that helps. It really isn't that complicated.