Issue
I have an interface I
with a method that allows it to interact with another I
:
public interface I {
I interactWith(I other);
}
Then I have a few classes that implement this interface, let's say A
, B
, C
and D
. Some of these interact with any other in the same way, so the implementation of the method is easy. Some others interact in different ways instead depending on the type of the other object, so i.e the interaction B
-A
is different from B
-C
and B
-D
. The naive implementation of the method for B
would be a mess of typechecking/instanceof
and feels like there's a better solution, so what's the correct approach?
I tried adding a default method interactWith(A other)
in both the interface and the B
class but it never gets called. Why is overloading not choosing the more specific method?
Edit: added sample code, also available here: https://onlinegdb.com/fakHVDDpSX
public interface I {
I interactWith(A other);
I interactWith(I other);
}
public class B implements I {
public I interactWith(A other) {
System.out.println("I'd like this to get called");
}
public I interactWith(I other) {
System.out.println("this get called even when other is of type A");
}
}
public static void main(String []args) {
List<I> list = Arrays.asList(new A(), new B());
list.get(1).interactWith(list.get(0));
}
Solution
Without seeing your code, in particular how you are declaring variables and their types, I am guessing you are running into a common confusion with how Java does dispatch. You are probably expecting behavior that is known as multiple dispatch, while Java only supports single dispatch. Here's the wikipedia page about multiple dispatch, and how you can kind of emulate that behavior in Java: https://en.wikipedia.org/wiki/Multiple_dispatch#Java
The gist is that Java needs to know the static types of both the parameter and the receiver of the method call to be able to choose the more specific overload. For example:
ublic class Main {
public static void main(String[] args) {
I a = new A(); // runtime type is `A` but static type is `I`
A a2 = new A(); // both runtime and static types are `A`
I b = new B(); // runtime type is `B` but static type is `I`
B b2 = new B(); // both runtime and static types are `B`
C c = new C();
p(b.interactWithOther(a)); // got I Main$A@4617c264
p(b.interactWithOther(a2)); // got I Main$A@36baf30c even though static type of a2 is A, b is an I, so it "doesn't have" the overloaded method
p(b.interactWithOther(c)); // got I Main$C@7a81197d
p(b2.interactWithOther(a)); // got I Main$A@4617c264
p(b2.interactWithOther(a2)); // got A Main$A@36baf30c only in this case is there specific enough type information to call the specific overload
p(b2.interactWithOther(c)); // got I Main$C@7a81197d
}
static void p(Object o) { System.out.println(o); }
static public interface I {
I interactWithOther(I other);
}
static class A implements I {
@Override
public I interactWithOther(I other) { return other; }
}
static class B implements I {
@Override
public I interactWithOther(I other) { System.out.print("got I "); return other; }
public A interactWithOther(A other) { System.out.print("got A "); return other; }
}
static class C implements I {
@Override
public I interactWithOther(I other) { return other; }
}
static class D implements I {
@Override
public I interactWithOther(I other) { return other; }
}
}
Notice how got A
is only printed when the static type of the receiver is B
and the static type of the parameter is A
, rather than I
s.
You can play around with it here: https://replit.com/@anqit/NegligibleMustyDatamining#Main.java
Answered By - anqit Answer Checked By - Terry (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.