Reputation: 42622
I have a function which first check the type of the passed argument:
public void myFunc(Object myObj){
if(myObj instanceof Student){
Student p = (Student) myObj;
}else{
Teacher p = (Teacher) myObj;
}
//after above check I want to handle p in a generic way
//of course the following p is not resolved...
p.getName();
p.registerSelf();
}
p
always needs to cast first. How to make the compiler first know p's type then invoke the common function both Teacher
& Student
have .
My Person and Teacher are generated automatically by using apache avro. I am not able to define the two classes(Person & Student) to extends the same class.
Upvotes: 0
Views: 173
Reputation: 3356
Assuming you cannot let extend the classes from an interface, you have to use some kind of reflection. A possible solution could be the following:
public void myFunc(Object myObj) {
if (myObj instanceof Student) {
Student p = (Student) myObj;
} else {
Teacher p = (Teacher) myObj;
}
//after above check I want to handle p in a generic way
//of course the following p is not resolved...
// define possible classes for invoking methods
List<Class<?>> possibleClasses = new ArrayList<Class<?>>() {{
add(Student.class);
add(Teacher.class);
add(NewUnknown.class); // just in case for more possibilities
}};
if (possibleClasses.contains(myObj.getClass())) {
try {
// directly invoking these methods, assuming,
// they exist in the defined classes
myObj.getClass().getMethod("getName").invoke(myObj);
myObj.getClass().getMethod("registerSelf").invoke(myObj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
// handle exception, if method is not available in current class
}
}
}
Upvotes: 0
Reputation: 39477
Have Student and Teacher extend from a common parent - say Person. Put the methods getName and registerSelf in Person. So then type-case to Person unconditionally and call the common methods which you put in Person.
OK, "My Person and Teacher are generated automatically by using apache avro. I am not able to define the two classes(Person & Student) to extends the same class."
This part was not in the original question, I think.
Based on that new information I would say:
1) I have similar problem with generated classes in one of my projects. I don't think there's a very good solution unless you somehow force Student and Teacher to implement some common interface after you've generated these classes (and without changing the generated classes manually /I guess you will want that requirement as you might be keeping them in some version control system/). I suggest you post a new question, as an important statement was not part of its initial version.
2) Also you might want to look at http://en.wikipedia.org/wiki/Decorator_pattern Not sure if it is applicable to your case but you check it out, maybe it is.
3) You can use reflection as grexter89 pointed out. That's the best for your case maybe.
Upvotes: 1
Reputation: 1102
If you really have no way to impelement an Interface
, take a look at Reflection
.
Here's an example on how to use it
Upvotes: 0
Reputation: 5762
Student p
and Teacher p
have scope until the if
clause. So declare Person p = null
at first.
And if you want to do same thing with each person then why use instanceof
. Simply extract the method to superclass and then override them in subclass. Beware of instanceof
Upvotes: 0
Reputation: 19294
If Teacher
& Student
have similar methods you want to call, create interface (or super class) with these methods, then use myFunc(ParentClass myObj)
and no need to cast anything:
public void myFunc(ParentClass myObj){
myObj.getName();
myObj.registerSelf();
}
Upvotes: 0
Reputation: 9038
First of all, your code does not compile.
Secondly:
public interface Person{
String getName();
void registerSelf();
}
public class Student implements Person{
....
}
public class Teacher implements Person{
....
}
and your code changes to
public void myFunc(Object myObj){
Person p = null;
if(myObj instanceof Student){
p = (Student) myObj;
}else{
p = (Teacher) myObj;
}
//after above check I want to handle p in a generic way
//of course the following p is not resolved...
p.getName();
p.registerSelf();
}
Upvotes: 0