2

PHPからC#に移行しています。

PHPでは、抽象クラスを使用して「カスケードオーバーライド」パターンを作成するのは簡単で簡単でした。基本的に、「継承クラスに同じシグネチャを持つメソッドがない限り、基本クラスのメソッドがそれを処理します」。

ただし、C#では、基本クラスと継承クラスでキーワードnewvirtualabstractoverrideのさまざまな組み合わせを試して、この単純なカスケードオーバーライドパターンを実行する正しい組み合わせが最終的に得られるまで、約20分を費やしました。

したがって、以下のコードが私が望むように機能する場合でも、これらの追加されたキーワードは、C#が抽象クラスではるかに多くのことを実行できることを示唆しています。これらのキーワードの例を調べて、基本的にそれらが何をするかを理解しましたが、この単純な「カスケードオーバーライド」パターン以外にそれらを使用する実際のシナリオを想像することはできません。日常のプログラミングでこれらのキーワードを実装する実際の方法は何ですか?

動作するコード:

using System;

namespace TestOverride23433
{
    public class Program
    {
        static void Main(string[] args)
        {
            string[] dataTypeIdCodes = { "line", "wn" };
            for (int index = 0; index < dataTypeIdCodes.Length; index++)
            {
                DataType dataType = DataType.Create(dataTypeIdCodes[index]);
                Console.WriteLine(dataType.GetBuildItemBlock());
            }

            Console.ReadLine();
        }
    }

    public abstract class DataType
    {
        public static DataType Create(string dataTypeIdCode)
        {
            switch (dataTypeIdCode)
            {
                case "line":
                    return new DataTypeLine();
                case "wn":
                    return new DataTypeWholeNumber();
                default:
                    return null;
            }
        }

        //must be defined as virtual
        public virtual string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the default datatype class";
        }
    }

    public class DataTypeLine : DataType
    {
        public DataTypeLine()
        {
            Console.WriteLine("DataTypeLine just created.");
        }
    }

    public class DataTypeWholeNumber : DataType
    {
        public DataTypeWholeNumber()
        {
            Console.WriteLine("DataTypeWholeNumber just created.");
        }

        //new public override string GetBuildItemBlock()  //base method is erroneously executed
        //public override string GetBuildItemBlock() //gets error "cannot override inherited member because it is not marked virtual, abstract, or override"
        public override string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the WHOLENUMBER class.";
        }
    }

}
4

3 に答える 3

8

virtual/overrideはコアポリモーフィズムペアです。あなたはすでにこれらをクラックしたように聞こえます

abstractに似virtualていますが、実用的な基本実装はありません。ユースケース:おそらく、実際の実装がバイトを使って何かをする必要Streamがある場合。これにより、クラスは強制的にabstract

new通常は避ける必要があります。ポリモーフィズムを壊します...最も一般的なケースは、より具体的な署名/リターンタイプで再公開することです(チェーンの上位に表示されないため、おそらく封印されたクラスで...)- SqlConnection.CreateCommand(vs DbConnection.CreateCommand)を参照してください、または(おそらくもっと顕著に)IEnumerator<T>.Current(vs IEnumerator.Current

于 2009-06-16T08:43:33.520 に答える
3

あなたはすでにあなたの例から理解しているvirtualようoverrideです、それで:

  • ' abstract'の代わりに''をメンバーに適用することもできvirtualます。その場合、メソッドの実装を指定しません(' ;'署名の直後)。これにより、すべての具象子孫がメソッドを実装するように強制されます。

  • ' new'は継承とは関係ありませんが、代わりにメンバーの子孫クラスで使用して、まったく同じシグネチャを持つ基本クラスのメンバーを非表示にすることができます。

一言で言えば ;)

于 2009-06-16T08:45:18.540 に答える
1

他の答えに加えて。

子クラスが独自の処理を実行できるようにしたい場合、処理なし、または関数の親クラス処理を呼び出すだけの場合にオーバーライドします。オーバーライドまたは仮想関数は、子孫クラスに実装する必要はありません。

基本クラスで処理を実行したくないが、そのメソッドを継承クラスで実装したい場合は抽象化します。(継承するクラスの動作が大幅に異なる可能性がある場合に最適です)。クラスに抽象メソッドしか含まれていない場合、それは事実上インターフェイスタイプです。抽象として指定された関数は、子クラスに実装する必要があります(実装しない場合、コンパイラはエラーをスローします)。

于 2009-06-16T08:52:46.590 に答える