8
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?

Learner
  • 1,503
  • 6
  • 23
  • 44

5 Answers5

2

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() {

    }
}
Braj
  • 46,415
  • 5
  • 60
  • 76
  • 1
    With this solution I will not be able to call methods on `sc` which exists in Parent class. I edited my question to mention this. Thanks. – Learner May 06 '14 at 11:35
  • have you made `Child1` implements `FooInterface` same for `Child2`? – Braj May 06 '14 at 11:49
  • This is what I mentioned in My Solution, only difference is that in my solution, reference is of type `Parent` and thus I need to use `instanceof` once to see if it is of type `FooInterface`. – Learner May 06 '14 at 12:56
  • so you don't want to change your design then its not possible as I told you *parent class/interface doesn't have any knowledge about the child class.* how would parent class/interface know that child has created x methods? – Braj May 06 '14 at 13:00
  • How about my solution that I had mentioned in the question? it does solve my problem. But is good approach is what I want to know? – Learner May 06 '14 at 14:32
2

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();
}
Learner
  • 1,503
  • 6
  • 23
  • 44
1

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.

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • 1
    Look at the OP question again. `Parent` doesn't have any `foo()` method. – Braj May 06 '14 at 09:05
  • 1
    How can you call a method on the reference of interface where interface has not declared that method? Look at my post. – Braj May 06 '14 at 09:10
  • @Braj Now you should read OP question again, the interface define a method foo. – Roman C May 06 '14 at 09:11
  • Read this line not solution part **Here method foo() only exists in the Child classes and CAN NOT be added to the Parent class (not even abstract method)** – Braj May 06 '14 at 09:12
  • @Roman C, the interface is part of my solution And what am asking is whether my solution is good or is there a better way to do it. – Learner May 06 '14 at 09:13
  • @Braj read more that OP notes: `The approach that I am thinking is to define an interface say FooInterface with foo()` – Roman C May 06 '14 at 09:13
  • @Braj What a code review? Are you not a java programmer? Or anything wrong with the format the answer? Or you just kidding me out there? – Roman C May 06 '14 at 09:15
  • @RomanC your answer is best suited for this condition. +1 for this approach. – Braj May 06 '14 at 09:18
  • 2
    @Learner One more comment to you, when designing your classes consider coding to interfaces, not classes. – Roman C May 06 '14 at 09:20
  • 1
    @RomanC, With this solution I will not be able to call methods on `obj` which exists in `Parent` class. Yes, I understand advantage of code to interface but this is legacy code and I CAN NOT modify `Parent` class. – Learner May 06 '14 at 09:21
  • @Learner if you need a parent class then typecast it directly or use a method in the interface that return a parent type. Why there isn't this in the question that you want to use parent? See you have another incomplete answer from %Braj. – Roman C May 06 '14 at 09:25
0

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

Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
  • Well, that's what I think is not a good approach and hence don't want to use it. If there are multiple child classes then it would be ugly. Isn't it ? – Learner May 06 '14 at 09:10
0

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.

davioooh
  • 23,742
  • 39
  • 159
  • 250