JHollanti
JHollanti

Reputation: 2413

How to infer subtype in supertype

Say you have a super-class. In that super class you want to pass runtime object of itself (this) as a parameter to an overloaded method. Trick is, this overloaded method is overloaded by sub-class type. When you try to do it, you'll get a

method ... is not applicable(actual argument ... cannot be converted to ... by method invocation conversion)

Instead you would need to implement the method separately in each subtype (just to get the correct runtime class), which is a lot of duplicate effort when the contents of the method are identical.

e.g:

public class InferTypeTest {

    public static void main(String[] args) {
        SubClass1 s1 = new SubClass1();
        s1.sayHi();
    }

    public static void sayHi(SubClass1 clz) {
        System.out.println("clz 1");
    }

    private abstract static class SuperClass{
        public void sayHi() {
            InferTypeTest.sayHi(this);
        }
    }

    private static class SubClass1 extends SuperClass{

    }

}

Upvotes: 2

Views: 531

Answers (2)

David Mathias
David Mathias

Reputation: 335

BodyNode is a NodeWithChildren DivNode is a NodeWithChidren NodeWithChildren is a DomNode DomPrinterVisitor is a DomNodeVisitor DomNodeVisitor's visitor can visit "BodyNode" or "DivNode, But you are passing "NodeWithChildren" to visit. Here BodyNode is a NodeWithChildren but NodeWithChildren is not BodyNode/

Theary is if B extends A, you can say B is a A/ not A is a B.

Upvotes: 0

Neil
Neil

Reputation: 55402

Yes, this is how double dispatch works, you have to override the accept method in each subclass like this:

    private static abstract class NodeWithChildren implements DomNode {
        /* snip */
        public void accept(DomNodeVisitor visitor) {
            for (DomNode child : children) {
                child.accept(visitor);
            }
        }
    }

    private static class BodyNode extends NodeWithChildren {
        public void accept(DomNodeVisitor visitor) {
            visitor.visit(this);
            super.accept(visitor);
            visitor.visited(this);
        }
    }

    private static class DivNode extends NodeWithChildren {
        public void accept(DomNodeVisitor visitor) {
            visitor.visit(this);
            super.accept(visitor);
            visitor.visited(this);
        }
    }
}

Upvotes: 2

Related Questions