Instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose.In the example below I removed abstract from A to illustrate how it works with different types.
Instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose.In the example below I removed abstract from A to illustrate how it works with different types.
The trick is that when an object is asked to visit a visitor, the object itself chooses the correct accept method in the visitor. The "instanceof"-check is resolved through polymorphism.(I doubt that it's more efficient than an instanceof though.) interface Visitor { public A accept(A a); public B accept(B b); } class A { public A sum(A a) { System.out. Println("A.
Sum(A) called"); return null; } public A visit(Visitor sv) { return sv. Accept(this); } } class B extends A { public B sum(B b) { System.out. Println("B.
Sum(B) called"); return null; } public B visit(Visitor sv) { return sv. Accept(this); } } public class Test { public static void main(String args) { A a = new A(); B be = new B(); A basa = new B(); a. Visit(new SumVisitor(b)); // a.
Sum(b); b. Visit(new SumVisitor(b)); // b. Sum(b); basa.
Visit(new SumVisitor(b)); // basa. Sum(b); basa. Visit(new SumVisitor(basa)); // basa.
Sum(basa); } static class SumVisitor implements Visitor { A arg; SumVisitor(A arg) { this. Arg = arg; } public A accept(A a) { return a. Sum(arg); } public B accept(B b) { return b.
Sum(arg); } } } Output: A. Sum(A) called B. Sum(B) called B.
Sum(B) called B. Sum(B) called Disclamer; It was a while ago I wrote a visitor, so please correct me if I have any bugs in this (almost untested) code snippet. Or better, edit the post yourself and improve it :).
OK, it seems overkill to me and I'd like to test it's efficiency (to evaluate the difference between instanceof and polymorphism). I'll post here if I have some figures. – dodecaplex Jun 30 '10 at 12:50 There is a bug in SumVisitor, but I'm not clever enough to fix it - you never use arg and just add everything to itself, meaning that this x.
Visit(new SumVisitor(y)) just a roundabout way of writing x. Sum(x). Just changing accept(B) to return b.
Sum(arg) or return arg. Sum(b) won't work as both resolve to sum(A) then. – gustafc Jun 30 '10 at 14:37 @gustafc, Yep.
You're right. I had a bad feeling about it when I posted it... thus the disclamer ;) So I suppose some double dispatch is needed. One way to fix it would be to divide the SumVisitor into a LHS visitor and a RHS visitor.
– aioobe Jun 30 '10 at 15:31.
Since B instances can be summed with A instances using myA. Sum(myB), you should be able to change B's definition of sum so that it does override, unless of course sum is a placeholder and isn't something that should be commutative. UPDATE: If this is insufficient, you could start getting fancy with generics.
Here's a rough pass at what I mean: public abstract class A { public T sum(T a) { System.out. Println("A. Sum(A) called"); return null; } public static void main(String args) { B be = new B(); b.
Sum(b); A basa = new B(); basa. Sum(b); basa. Sum(basa); } public static class B extends A { @Override public T sum(T b) { System.out.
Println("B. Sum(B) called"); return null; } } } @aioobe is right that the generally accepted work-around is to use the Visitor pattern. I'm offering these as less complete but less verbose alternatives.
Well, I could add in class B the following method to force the dynamicity: public A sum(A a) { if (a instanceof B) { return this. Sum((B) a); } else { return super. Sum(a); } } but somehow it will fail my purpose (provide a more efficient implementation as instanceof is usually known as very inefficient).
My question was rather on the design pattern, as it seemed to me that this purpose was quite usual. – dodecaplex Jun 30 '10 at 10:24 @dodecaplex My point was that sum is generally understood to be commutative. If you are in fact implementing a sum, a signature of @Override B sum(A a) should be enough to get you what you want while still being commutative.
I realized that sum might just be a placeholder, hence the caveat at the end. – Hank Gay Jun 30 '10 at 10:29 I don't get how this works. I removed abstract from A, and tried to invoke b.
Sum(a), but it still goes to B's implementation of sum. – aioobe Jun 30 '10 at 10:42 @aioobe If you want A. Sum(A) to get called, you'd need to actually instantiate an A, e.g. , A basa = new A();.
Alternatively, you could create a new subclass of A that doesn't override A. – Hank Gay Jun 30 '10 at 11:04.
It's used in several places in the JDK where they want to provide a "fast path" for certain well-known implementations of an abstract class or interface. The usual advice applies here: "Test, don't guess.
You are right. It's just what I read from discussion on several mailing list. I think some people use it as an argument to justify certain de – dodecaplex Jun 30 '10 at 12:49.
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.