代码之家  ›  专栏  ›  技术社区  ›  geejay

多态性(非)与C中的访问者模式断开(以及新的而非重写)

  •  1
  • geejay  · 技术社区  · 15 年前

    我有以下代码:

    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); }
    }
    

    有什么理由 Accept(Visitor v) 调用时将选择方法 new Node().Accept(new VisitorSpecial())

    更新:好吧,糟糕的是,我意识到我在访客中使用的是“新”而不是覆盖。现在我知道为什么“新突破多态性”。这使我的问题非常愚蠢。谢谢你的帮助。

    2 回复  |  直到 15 年前
        1
  •  2
  •   xtofl Adam Rosenfield    15 年前

    我想你问的是特定语言的问题(C?)。选择最合适的重载取决于语言(注意:不重写!)给出了一个论点。这取决于 函数查找类型 它使用:静态(编译时)或动态(运行时)。

    以防你的语言使用 静态绑定 ,它可能会选择最具体的呼叫,在这种情况下, n.Accept( new VisitorSpecial() ) 会调用第二个重载。然而,

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

    将静态绑定到 Node::Accept( Visitor ) 功能。

    如果语言使用 动态绑定 ,它可以根据参数的实际运行时类型选择被调用的函数。

    一般来说,你可以 周围工作 不使用重载(这只是语法上的糖分)的问题是:区分 AcceptVisitor AcceptSpecialVisitor . 添加一个 AcceptManager AcceptJustSimplyMy 也是。

        2
  •  4
  •   workmad3    15 年前

    不知道为什么要选择它(字面上可能是因为它在类声明中是第一个并与提供的参数匹配),但是

    Accept(VisitorSpecial v)
    

    在这种情况下,函数是没有意义的,似乎是由于对多态性的误解。请尝试以下操作以了解原因:

    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); }
    }
    

    有了以上内容,请致电

    someNode.Accept(new VisitorSpecial());
    

    将产生输出

    > In special visitor