1

次のコードがあります。

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())

更新: OK、悪いことに、オーバーライドの代わりにビジターで「new」を使用していることに気付きました。これで、「new breaks polymorphism」の理由がわかりました。これは私の質問を完全にばかげています。助けてくれてありがとう。

4

2 に答える 2

4

なぜそれが選択されるのかはわかりません (クラス宣言の最初にあり、提供された引数と一致するため、文字通りそうである可能性があります) が、

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
于 2009-10-19T10:08:14.080 に答える
2

特定の言語 (C#?) について質問していると思います。与えられた引数に最も適切なオーバーロード (注: オーバーライドしないでください!) を選択するのは言語次第です。これは、使用する関数ルックアップのタイプ(静的 (コンパイル時) または動的 (実行時)) によって異なります。

言語がstatic bindingを使用している場合、おそらく最も具体的な呼び出しが選択されます。この場合、n.Accept( new VisitorSpecial() )2 番目のオーバーロードが呼び出されます。でも、

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

関数に静的にバインドされNode::Accept( Visitor )ます。

言語が動的バインディングを使用する場合、引数の実際の実行時の型に基づいて呼び出される関数を選択できます。

一般に、オーバーロードを使用しないことで問題を完全に回避できます。オーバーロードは単なる構文糖衣です。 と を区別AcceptVisitorしてAcceptSpecialVisitorください。と も追加しAcceptManagerますAcceptJustSimplyMy

于 2009-10-19T10:25:19.693 に答える