views:

266

answers:

2

I have the following code:

class Visitor 
{
    internal virtual void Visit(Node n) { }
}

class VisitorSpecial : Visitor 
{
    internal new void Visit(Node n) { }
}

class Base
{ 
    internal virtual void Accept(Visitor v) { }
    internal virtual void Accept(VisitorSpecial v) { }
}

class Node : Base
{
    internal override void Accept(Visitor v){ v.Visit(this); }
    internal override void Accept(VisitorSpecial v){ v.Visit(this); }
}

Is there any reason why the Accept(Visitor v) method would be chosen when calling new Node().Accept(new VisitorSpecial())

Update: OK, my bad, I realized I was using "new" in the visitor instead of override. Now I know why "new breaks polymorphism". This makes my question totally stupid. Thanks for the help.

+4  A: 

Not sure why it would be chosen (it could literally be because it is first in the class declaration and matches the argument provided), but the

Accept(VisitorSpecial v)

functions are pointless in this situation and seems to be down to a misunderstanding of polymorphism. Try the following to see why:

class Visitor 
{
    internal virtual void Visit(Node n) { Console.WriteLine("In normal visitor"); }
}

class VisitorSpecial : Visitor 
{
    internal override void Visit(Node n) { Console.WriteLine("In special visitor"); }
}

class Base
{ 
    internal virtual void Accept(Visitor v) { }
}

class Node : Base
{
    internal override void Accept(Visitor v){ v.Visit(this); }
}

With the above, calling

someNode.Accept(new VisitorSpecial());

will produce the output

> In special visitor
workmad3
+2  A: 

I think you ask the question for a specific language (C#?). It's up to the language to select the most appropriate overload (note: not override!) given an argument. That depends on the type of function lookup it uses: static (compile-time) or dynamic (run-time).

In case your language uses static binding, it will probably choose the most specific call, in this case, n.Accept( new VisitorSpecial() ) would call the second overload. However,

Visitor v = new VisitorSpecial();
n.Accept( v );

would be statically bound to the Node::Accept( Visitor ) function.

In case the language uses dynamic binding, it can choose the called function based on the actual runtime type of the argument.

In general, you can work around the problem altogether by not using overloading, which is merely syntactic sugar: make a distinction between AcceptVisitor and AcceptSpecialVisitor. Add an AcceptManager and AcceptJustSimplyMy too.

xtofl