public class Parent {
....
}
public class Child1 extends Parent {
....
public void foo() {
....
}
}
public class Child2 extends Parent {
....
public void foo() {
....
}
}
Here method foo() only exists in the Child classes and CAN NOT be added to the Parent class (not even abstract method). In this situation when I want to call the foo() method on obj which is Parent class's reference then I need to use intanceof with multiple if..else which I want to avoid.
Parent obj = ...// Object of one of the child classes
obj.foo();
EDIT: I Need to use type of obj as Parent only. Else I will not be able to call methods on obj which exists in Parent class.
My Solution: The approach that I am thinking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
Is there a better approach ? Or any improvement to this one?
You can't do it with parent object reference until an unless method is declared in parent class/interface itself.
You have to downcast it to child class because parent class/interface doesn't have any knowledge about the child class other than the contract defined between them.
Here contract means abstract methods.
you can try in this way where there is no need to put a check it.
FooInterface sc =new Child1();
sc.foo();
...
interface FooInterface{
void foo();
}
public class Parent {
}
public class Child1 extends Parent implements FooInterface{
public void foo() {
}
}
public class Child2 extends Parent implements FooInterface{
public void foo() {
}
}
The approach that I am finally taking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
Parent obj = ...// Object of one of the child classes
.....
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
The polymorphism is applied on object reference, not a type. When you call
FooInterface obj = ...// Object of one of the child classes
obj.foo();
the child class method foo() is called.
If you want to typecast only then there is no need of adding interface. You can typecast it to your desired class and call the method. Example
public class HelloWorld {
public static void main(String args[]) throws FileNotFoundException {
SuperClass sc =new Child1();
if(sc instanceof Child1)//Do same for Child2
((Child1)sc).foo();
}
}
class SuperClass {
}
class Child1 extends SuperClass{
public void foo(){
System.out.println("From child1");
}
}
class Child2 extends SuperClass{
public void foo(){
System.out.println("From child2");
}
}
Output :
From child1
You could implement an AbstractChild inheriting from Parent and then extend this class instead of Parent:
public class Parent {
....
}
public abstract class AbstractChild extends Parent{
public abstract void foo();
}
public class Child1 extends AbstractChild {
....
public void foo() {
....
}
}
public class Child2 extends AbstractChild {
....
public void foo() {
....
}
}
So you need to only check if your instance is instanceof AbstractChild.
Related
I have two classes:
public abstract class Parent{
Object parentObj;
public abstract Object something();
}
And
public class Child extends Parent{
#Override
public Object something(){
return new Object();
}
}
Is there any way to do something in the parent to set parentObj every time the something() method is called?
I don't want to set parentObj in every child.
Sure:
public abstract class Parent{
Object parentObj;
public final Object something() {
parentObj = ...;
return doSomething();
}
protected abstract Object doSomething();
}
and
public class Child extends Parent{
#override
protected Object doSomething(){
return new Object();
}
}
That's called the template method pattern.
I have a class hierarchy which looks somewhat like this:
class Parent { }
class Child1 extends Parent {}
class Child2 extends Parent {}
class Child3 extends Parent {}
In another class I have methods looking like this:
void doSomething(Parent p) { //default }
void doSomething(Child1 c) { //implementation for Child 1 }
void doSomething(Child2 c) { //implementation for Child 2 }
Currently, when I have something like this
Parent p = new Child2();
doSomething(p);
the first method, doSomething(Parent) is called instead of doSomething(Child2)
Let's assume I have a list of items with the static type of Parent and a dynamic type of ChildN. How can I assure the method, provided for the dynamic type is called, without casting. Only for Child3 (no specific doSomething method) I want to call the default implementation.
What you are looking for is called "multi dispatch or "dynamic dispatch" - and doesn't exist in Java.
In Java, the compiler decides which method to pick in case of overloading. (and that is what happens when you have three methods with the same name but different parameter types). This happens at compile time, and if your "runtime" Parent object happens to be a Child1 object; that doesn't matter. Because the compiler fixed the method to call - as said: java doesn't support dynamic dispatch.
In that sense, the correct Java solution would be to put a method "doSomething()" on your Parent class; and have each child override that method to the specific thing.
In case "doSomething()" doesn't really "fit" into this class; you can have a look into the visitor pattern. Another option would be to use instanceof ... but then you should "hide" the corresponding if/else chain ... again using polymorphism, like:
interface DoIt { void doSomething() }
class ParentDoIt implements DoIt ...
same for Childs
class DoItFactory {
DoIt getDoIt(Parent p) {
if (p instanceof Child1) return new Child1DoIt(p)
...
A solution could be that the doSomething method uses logic from the parameter:
class Parent {
public void neededMethod() {//default}
}
class Child1 {
public void neededMethod() {//implementation for Child 1}
}
Then in your code:
void doSomething(Parent p) {
//more code
p.neededMethod();
// code
}
If this solution does not fit you because you need some kind of a dispatcher, then you will have to use instanceof and then call the proper method:
void doSomething (Parent p) {
if (p instanceof Child1) doSomethingWithChild1(p);
else if (p instanceof Child2) doSomethingWithChild2(p);
...
else defaultSomething(p);
}
I would do it like this.
interface SomeAction { void doSomething(); }
class Parent implements SomeAction { //override doSomething here }
class Child1 extends Parent {//override doSomething here }
class Child2 extends Parent {//override doSomething here }
class Child3 extends Parent { // no need to override here}
Now
In another class I have methods looking like this
void doSomething(SomeAction p) { //default }
Parent p = new Child2();
doSomething(p);
p.doSomething(); // would call Child 2
I have parent class and a child class, both of having a method m1 with same signature (Override), can I call parent class method in following scenario. I dont want to change child class method.
// Super class
public class Parent
{
public void m1()
{
System.out.println("Parent method");
}
}
// Sub class
public class Child extends Parent {
#Override
public void m1() {
System.out.println("Child method");
}
}
// User class
public class Kavi {
public static void main(String[] args) {
Parent p = new Child();
p.m1();
}
}
I want to call parent class m1 method. I know that I can use super in child class method to call its parent method. but I have no right to change the source code of child class. and I have to call it from child class object. please anybody help !!! is it possible in java ??
While creating the Object you are using reference of Super class but your object is of child class, so while calling m1() method the overrided method will be invoked. If you want the method of the super class to be invoked then object should be of Super class. As :
Parent parent=new Parent();
parent.m1();
OR
you can invoke the super class m1() method from the child class.
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
OR ELSE
import java.lang.reflect.*;
class A {
public void method() {
System.out.println("In a");
}
}
class B extends A {
#Override
public void method() {
System.out.println("In b");
}
}
class M {
public static void main( String ... args ) throws Exception {
A b = new B();
b.method();
b.getClass()
.getSuperclass()
.getMethod("method", new Class[]{} )
.invoke( b.getClass().getSuperclass().newInstance() ,new Object[]{} ) ;
}
}
Without changing the code, you can't do this. You're essentially talking about p.super.m1() which isn't legal in Java. If you want your parent to act like a parent, don't make it a child.
If both parent and child are stateless, you could create a facade over them and explicitly manage the state; this would work, but I wouldn't recommend it.
public class Facade extends Parent {
public enum State {PARENT, CHILD};
private final Child delegate;
private State state = State.CHILD;
public Facade(Child delegate) {
this.delegate = delegate;
}
#Override
public void m1() {
if (State.CHILD == state) {
delegate.m1();
} else {
super.m1();
}
}
public void setState(State state) {
this.state = state;
}
}
This is a purely academic exercise - I can't think of a single good reason to do this in the real world. If you're using an OO language, don't fight the OO paradigm!
I think it not possible. There are two ways to call a parent class method
1.) crate object of parent class as
Parent p = new Parent();
2.) Use super in child class method as
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
Apart from the already mentioned way, you can declare both the methods as static.
so when you do this
Parent p = new Child();
p.m1();
the static method of parent class would be called and the output will be "Parent method"
Note : The static keyword in Java means that the variable or function is shared between all instances of that class as it belongs to the type, not the actual objects themselves.
So if you have a variable:
private static int i = 0; and you increment it ( i++ ) in one instance, the change will be reflected in all instances.
If you can not use super then instead of creating the child class object you can directly use
Parent p = new Parent();
p.m1();
if you can't even modify the code inside main method then I think it's not possible .
When I tried to understand how to work with collections in java, I realised that I don't understand how polymorphism works for inner classes.
Simple code example:
class Parent {
public static void main(String[] args) {
new Parent().newInnerClass().myMethod();
new Child().newInnerClass().myMethod();
}
public I newInnerClass() {
return new InnerClass();
}
private final class InnerClass implements I {
#Override
public void myMethod() {
System.out.println("parent inner class");
foo();
}
}
public void foo() {
System.out.println("foo from parent");
}
}
class Child extends Parent {
public void foo() {
System.out.println("foo from child");
}
}
interface I {
void myMethod();
}
result:
parent inner class
foo from parent
parent inner class
foo from child
Therefore first link affects the third method invocation. It is surprising to me.
Initially I thought that needed methods selected accordind to the link. But new Parent().newInnerClass() and new Child().newInnerClass() are links to InnerClass from Parent.
Can you clarify my misunderstanding?
P.S.
If InnerClass was in Child and extended InnerClass from Parent - this behaviour wouldn't be surprising for me.
There are no special rules for polymorphism in inner classes.
Inner class differs from regular class in two things:
Inner class holds an implicit reference to its containing object
Inner class can access private methods of its containing class (not relevant here)
That's how you can rewrite your example without inner class:
class Parent {
...
public I newInnerClass() {
return new NotInnerClass(this);
}
...
}
class NotInnerClass implements I {
private final Parent containingObject;
public NotInnerClass(Parent containingObject) {
this.containingObject = containingObject;
}
#Override
public void myMethod() {
System.out.println("parent inner class");
containingObject.foo();
}
}
This code produces the same output as your, because when you invoke
new Child().newInnerClass().myMethod();
containingObject is a Child and containingObject.foo() is a regular polymorphic call.
When you use inner class, compiler does the same thing behind the scenes.
Is it possible to dynamically identify T as a return type depending on subclass Type?
I want something like the following:
public class Parent {
public <T extends Parent> T foo() {
return (T)this;
}
}
public class Child extends Parent {
public void childMethod() {
System.out.println("childMethod called");
}
}
And then to call:
Child child = new Child();
child.foo().childMethod();
Without defining the type like so:
Child child = new Child();
child.foo().<Child>childMethod(); // compiles fine
Thanks in advance!
You want this:
public class Parent<T extends Parent<T>> {
public T foo() {
return (T)this;
}
}
public class Child extends Parent<Child> {
public void childMethod() {
System.out.println("childMethod called");
}
}
Child child = new Child();
child.foo().childMethod(); // compiles
It is impossible in the Java type system for Parent to refer to the exact class of this. However, it can have a type parameter (say T) that subclasses can specify, as either themselves, or some other type (whatever they want), and use an abstract method to delegate the task of obtaining an instance of a that type T to the subclass.
public abstract class Parent<T> {
// the implementer is responsible for how to get an instance of T
public abstract T getT();
// in this case, foo() is kind of redundant
public T foo() {
return getT();
}
}
public class Child extends Parent<Child> {
public Child getT() {
return this;
}
public void childMethod() {
System.out.println("childMethod called");
}
}
Child child = new Child();
child.foo().childMethod(); // compiles