7

「派生からこんにちは」を期待しています。しかし、「ベースからこんにちは」を取得します。

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public virtual new void Method()
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

では、なぜ派生クラスのメソッドが呼び出されないのでしょうか。さらに重要なことに、xをDerived型にキャストせずに、派生クラスメソッドを呼び出すにはどうすればよいですか?

私の実際のアプリケーションでは、IBaseには他のいくつかの関連するメソッドがあり、DerivedはIBaseの2つのメソッドのみを置き換えます。

4

5 に答える 5

10

修飾子を使用するnewと、メソッドはその階層の仮想ディスパッチチェーンの一部ではないため、基本クラスで同じ名前でメソッドを呼び出しても、子クラスにリダイレクトされることはありません。overrideの代わりにメソッドをマークすると、new期待している仮想ディスパッチが表示されます。

また、メソッドにvirtualマークを付けることはできないため、派生クラスのメソッドから削除する必要があります(すでにそうなっています)。overridevirtual

メソッドを本当にオーバーライドしたくない場合は、状況によっては、継承をまったく使用しない方が適切な場合があります。インターフェースを排他的に使用したい場合があります。

public interface IFoo
{
    void Foo();
}

public class A : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am A, hear me roar!");
    }
}

public class B : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am B, hear me roar!");
    }
}

private static void Main(string[] args)
{
    IFoo foo = new A();
    foo.Foo();

    foo = new B();
    foo.Foo();

    Console.WriteLine();
    Console.WriteLine("Press any key to exit . . .");
    Console.ReadKey(true);
}
于 2012-11-13T15:33:32.023 に答える
3

これは基本的なポリモーフィズムです。

探している動作については、継承されたメソッドをオーバーライドするように派生メソッドを設定する必要があります。

public class Derived : Base
{
    public override void Method()
    {
        Console.WriteLine("Hello from the derived.");
    }
}
于 2012-11-13T15:28:57.330 に答える
2

子クラスではなくoverrideキーワードを使用してください。virtual new

したがって、コードは次のようになります。

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public override void Method() // The magic happens here!
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

hereで説明されているように、newキーワードは親メソッドを非表示にするために使用されますが、これは探しているものではありません。

于 2012-11-13T15:27:06.867 に答える
1

newキーワードは新しいメソッドを作成し、基本メソッドが非表示であることを示します。ただし、基本クラスコードはそれについて何も知らないため、派生クラスのコンシューマーのみが対象です。

overrideキーワードは、基本クラスの実装を新しいものでオーバーライドします。

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        // the next line was changed.
        public override void Method()
        {
            Console.WriteLine("Hello from the derived.");

            // note that if you want to call the original implementation, you do it like this:
            base.Method();
        }
    }

    static void Main(string[] args)
    {
        Base x = new Derived();
        x.Method();
    }
}
于 2012-11-13T15:32:27.573 に答える
0

Derived の new'd Method は Derived インスタンスにのみ存在し、基本実装を効果的に隠します。

しかし、IBase 型は Base の実装しか知らないので、それを呼び出します。

あなたの質問に答えるには、派生の実装を呼び出すには、次のようにします。

Derived d = new Derived();
d.Method();
((IBase)d).Method();

//Prints:
//Hello from the derived.
//Hello from the base.
于 2012-11-13T15:43:33.443 に答える