4

私は次のシナリオと混同しています、私たちはこのようなクラスのセットを持っています

public class A
{
    public virtual string SomeMethod()
    {
        return "A";
    }
}

public class B : A
{
    public override string SomeMethod()
    {
        return "B";
    }
}

public class C : B
{
    public new virtual string SomeMethod()
    {
        return "C";
    }
}

public class D : C
{
    public override string SomeMethod()
    {
        return "D";
    }
}

次のメソッドを呼び出すと

private void Test()
{
    A a = new D();
    B b = new D();
    C c = new D();
    D d = new D();
    Console.WriteLine(a.SomeMethod()); //The method in class B is being called
    Console.WriteLine(b.SomeMethod()); //The method in class B is being called
    Console.WriteLine(c.SomeMethod()); //The method in class D is being called
    Console.WriteLine(d.SomeMethod()); //The method in class D is being called
}

このような出力が得られます

BBDD

宣言された型のメソッドではなく、継承されたメソッドが呼び出されるのはなぜですか。また、クラスのメソッドがD毎回呼び出されないのはなぜですか。

4

3 に答える 3

4

(ie )SomeMethodのインスタンスを呼び出すと、利用可能な最も派生したバージョンを取得することが期待されます。それが継承の要点です。コードは基本クラスのインスタンスのみを処理する必要がありますが、それらのインスタンスが実際に派生クラスである場合は、特別な派生実装が呼び出されます。これは、メソッドをオーバーライドしたときに得られる動作です。AA foo = new <A or derived>()SomeMethod

これは、次のような一般的なシナリオを説明しています

A b = new B();
b.SomeMethod();  // B's implementation invoked

を使用newすると、メソッドをオーバーライドするのではなく、同じ名前の新しいメソッドを宣言することになります。 このメソッドは、それを宣言したクラスとその子にのみ存在し、基本クラスとその継承チェーンの一部ではありません。

では、何をしA a = new D(); a.SomeMethod();ますか?変数はとして宣言されてAいるため、変数に対して呼び出されるメソッド/プロパティなどは、で定義する必要がありますA新しいメソッドをC定義しました(そしてそれをオーバーライドします)が、このメソッドはに存在しないため、ここで呼び出すことはできません。(typeで宣言されている) の最も派生した実装はにあるので、これが呼び出される実装です。SomeMethodDASomeMethodAB

同じ話B b = new D(); b.SomeMethod();

新しいメソッドを実行する機会があるC c = new D(); c.SomeMethod()のは、私たちが到達したときだけです。これは、変数がであり、したがって、新しいメソッドが変数型で初めて宣言されるためです。そして、上記のように、最も派生した可能なバージョンが呼び出されます。これは、この場合、バージョンがによってオーバーライドされることを意味します。CSomeMethodD

そして、私たち全員が同じページにいることを願っていますD d = new D(); d.SomeMethod():)

他の人は良いリンクを投稿しています。これが役立つかもしれない別のスレッドです:C#とメソッドの非表示

そして、ここでの最後の例は、「new」メソッドがプライベートとして宣言されるさらに奇妙なシナリオを示しています。したがって、さらに派生したタイプは、「new」バージョンを継承するのではなく、実際にはメソッドのベースバージョンを継承します。http://msdn.microsoft.com/en-us/library/aa691135

于 2012-08-30T06:41:13.673 に答える
3

私はそれを別の方法で説明しようとしています。

virtual/overrideは、同じメソッドの動作を実装/変更することを意味します。これは、ポリモーフィズムの実装です。を使用newして、まったく新しいメソッドを作成します。たまたま別のメソッドと同じシグネチャを持っていますが、それとは何の関係もありません。

このメソッドを呼び出すときは、実際に呼び出すメソッドを選択するために、参照のタイプ(コンパイル時のタイプ)によって異なります。

あなたのコードは以下と同等です:

public class A
{
    public virtual string SomeMethod()
    {
        return "A";
    }
}

public class B : A
{
    public override string SomeMethod()
    {
        return "B";
    }
}

public class C : B
{
    public virtual string AnotherMethod()
    {
        return "C";
    }
}

public class D : C
{
    public override string AnotherMethod()
    {
        return "D";
    }
}

private void Test()
{
    A a = new D();
    B b = new D();
    C c = new D();
    D d = new D();
    Console.WriteLine(a.SomeMethod()); //The method in class B is being called
    Console.WriteLine(b.SomeMethod()); //The method in class B is being called
    Console.WriteLine(c.AnotherMethod()); //The method in class D is being called
    Console.WriteLine(d.AnotherMethod()); //The method in class D is being called
}

コンパイラーは、タイプC(およびD)の参照のためにAnotherMethodを呼び出すことを選択します。

于 2012-08-30T05:20:06.083 に答える
2

これはよく知られている動作です。メソッドを(with )で非表示newにすると、非表示タイプのインスタンスを介してメソッドにアクセスしている場合にのみ呼び出されます。基本クラスのインスタンスを使用する場合は、元のメソッドが使用されます。

表示はオーバーライドされません。

于 2012-08-27T10:46:49.220 に答える