This isn't a matter of polymorphism. This is a matter of method overloading When you pass instance3 to process() it will call process(SuperClass obj) because as far as the JVM is knows instance3 is a SuperClass since that's what you declared it as If you want the desired behavior (test#3 printing out "Process Instance 1"), you should define your process() method like so: private void process(SuperClass obj) { System.out. Println("Process " + obj.name()); } And your classes like this: abstract class SuperClass { String name() { return "SuperClass"; } } class Instance1 extends SuperClass { String name() { return "Instance 1"; } } class Instance2 extends SuperClass { String name() { return "Instance 2"; } } This will work because of dynamic (or late) method binding.
This isn't a matter of polymorphism. This is a matter of method overloading. When you pass instance3 to process(), it will call process(SuperClass obj) because as far as the JVM is knows, instance3 is a SuperClass since that's what you declared it as.
If you want the desired behavior (test#3 printing out "Process Instance 1"), you should define your process() method like so: private void process(SuperClass obj) { System.out. Println("Process " + obj.name()); } And your classes like this: abstract class SuperClass { String name() { return "SuperClass"; } } class Instance1 extends SuperClass { String name() { return "Instance 1"; } } class Instance2 extends SuperClass { String name() { return "Instance 2"; } } This will work because of dynamic (or late) method binding.
I'm not really following this as a solution. What I need is for the correct process() function to be called. What is being printed out is irrelevant in the demo.
I'm trying to find a better solution than using the instanceof operator. – Collin Peters Aug 5 at 18:36.
Either make it a virtual function inside hierarchy: abstract class SuperClass { public void process() { System.out. Println("Process super class"); } } class Instance1 extends SuperClass { public void process() { System.out. Println("Process instance1"); } } class Instance2 extends SuperClass { public void process() { System.out.
Println("Process instance2"); } } or check various approaches to multiple dispatch which is not natively supported in Java. http://en.wikipedia.org/wiki/Multiple_dispatch#Java.
The process() call takes a SuperClass (or sub-class) as an argument. It is not part of SuperClass – Collin Peters Aug 5 at 18:37.
If so, you should declare abstract method SuperClass.process() and implement it in the subclasses. To make test#3 work, you could add casting: test. Process((Instance1)instance3);.
Ugly. You could also define a factory class, and encapsulate type switching inside it. You'd have ProcessFactory with a ProcessObject getInstance(SuperClass obj) method that returns objects of type ProcessObjectInstance1 or ProcessObjectInstance2, with a method process().
ProcessFactory would work similar to your test#4.
This is what I currently doing. Basically turning the problem inside out a bit. Not sure if this counts as a visitor pattern.
Basically I just added an executeProcessor(Test test) abstract function within SuperClass, and the concrete classes implicitly know which function to call so they can simply use a cast. What do you think? Is this code smell?
Or a neat solution? Public class Test { private void process(Instance1 obj) { System.out. Println("Process Instance 1"); } private void process(Instance2 obj) { System.out.
Println("Process Instance 2"); } /** * @param args */ public static void main(String args) { Test test = new Test(); // Test 1 Instance1 instance1 = test. New Instance1(); instance1. ExecuteProcessor(test); // Test 2 Instance2 instance2 = test.
New Instance2(); instance2. ExecuteProcessor(test); // Test 3 (note this is not strongly typed) SuperClass instance3 = test. New Instance1(); instance3.
ExecuteProcessor(test); } abstract class SuperClass { public abstract void executeProcessor(Test test); } class Instance1 extends SuperClass { @Override public void executeProcessor(Test test) { test. Process((Instance1)this); } } class Instance2 extends SuperClass { @Override public void executeProcessor(Test test) { test. Process((Instance2)this); } } }.
As others have pointed out, this isn't really something you can do in Java. If you absolutely must, you can use reflection to do something like: private void process(SuperClass obj) { try { Class klass = obj.getClass(); Method m = this.getClass(). GetMethod("process", klass); m.
Invoke(this, obj); } catch (Exception e) { // default behavior System.out. Println("Process superclass"); } } I would really follow one of the other suggestions however.
Couple suggestions for cleaner way to do what you are doing: Options 1: Abstract method Define process() on Superclass, and override it on Instance1 and Instance2: abstract class SuperClass { public void process(String args) { System.out. Println("Process superclass"); } } class Instance1 extends SuperClass { @Override public void process(String args) { System.out. Println("Process Instance 1"); } } class Instance2 extends SuperClass { @Override public void process(String args) { System.out.
Println("Process Instance 2"); } } Option 2: Visitor Pattern Define an class that does the processing, and is an InstanceVisitor public interface InstanceVisitor { public void processSuperclass(Superclass obj, String args); public void processInstance1(Instance1 obj, String args); public void processInstance2(Instance2 obj, String args); } public class InstanceProcessor implements InstanceVisitor { public void processSuperclass(Superclass obj, String args) { System.out. Println("Process superclass"); } public void processInstance1(Instance1 obj, String args) { System.out. Println("Process Instance 1"); } public void processInstance2(Instance2 obj, String args) { System.out.
Println("Process Instance 2"); } } Then each subclass accepts a visitor, and calls the correct method: abstract class SuperClass { public void accept(InstanceVisitor v, String args) { v. VisitSuperclass(this, args); } } class Instance1 extends SuperClass { @Override public void accept(InstanceVisitor v, String args) { v. VisitInstance1(this, args); } } class Instance2 extends SuperClass { @Override public void accept(InstanceVisitor v, String args) { v.
VisitInstance2(this, args); } }.
I have a similar comment to the previous post. The process() function takes an instance of SuperClass as an argument. It doesn't have the process() function inside it.
I am going to clarify the original question – Collin Peters Aug 5 at 18:41.
Update: I like the idea of having a generic process() function that all Fruit are required to implement. But what if I now want to add a Lemon and want to juice that?
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.