3

Base クラスと Derived クラスの呼び出しメソッドを実現しようとしています。ただし、正しく行っているかどうかは少し混乱しています。Base クラスから値を設定し、それらを Derived クラスで使用したいと考えています。

namespace Inheritance
{
    using System;

    public class BaseClass
    {
        public BaseClass() { }

        protected string methodName;
        protected int noOfTimes;
        public void Execute(string MethodName, int NoOfTimes)
        {
            this.methodName = MethodName;
            this.noOfTimes = NoOfTimes;
        }
    }

    public class DerivedClass : BaseClass
    {
        public DerivedClass() : base() { }

        public void Execute()
        {
            Console.WriteLine("Running {0}, {1} times", base.methodName, base.noOfTimes);
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            DerivedClass d = new DerivedClass();
            d.Execute("Func", 2);
            d.Execute();

            Console.ReadLine();
        }
    }
}

質問: Execute の呼び出しを 2 回ではなく 1 回だけ使用して、上記と同じことを達成できますか?

上記の例が明確であることを願っています。それ以外の場合はお知らせください。追加の詳細を提供します。

ありがとう

4

4 に答える 4

8

免責事項、私の答えは、メソッドの継承とその実装を中心に展開するソリューションが必要であると想定しています。提供された他の回答も、質問に対する適切な解決策です。

派生クラスのメソッドをオーバーライドしたいようです。これを行うには、基本クラスでメソッドvirtualまたはをマークする必要がありますabstract。ただし、あなたの場合、派生クラス メソッドのシグネチャは異なります。これは、それがどのように機能するかを理解していないためのエラーであると想定しているため、修正しました。

この例では、派生クラスはoverrideC# キーワードである でメソッドをマークします。base.Execute(MethodName, NoOfTimes);次に、オーバーライドされた実装で基本クラスの実装を使用したいときに呼び出します。次に、独自のコードを挿入します。

baseは、継承チェーンによって派生メンバーに戻されることなく、現在のクラスのすぐ下にある基本クラスのメンバーにアクセスできるようにするもう 1 つのキーワードです。

abstractは読む価値がありますが、この場合は必須ではありません ( とは動作が異なりますvirtualが、 と組み合わせて使用​​することもできますoverride)。

namespace Inheritance
{
    using System;

    public class Program
    {
        internal protected class BaseClass
        {
            public BaseClass() { }

            protected string methodName;
            protected int noOfTimes;
            public virtual void Execute(string MethodName, int NoOfTimes)
            {
                this.methodName = MethodName;
                this.noOfTimes = NoOfTimes;
            }
        }

        internal class DerivedClass : BaseClass
        {
            public DerivedClass() : base() { }

            public override void Execute(string MethodName, int NoOfTimes)
            {
                base.Execute(MethodName, NoOfTimes);
                Console.WriteLine("Running {0}, {1} times", base.methodName, base.noOfTimes);
            }
        }

        static void Main(string[] args)
        {
            DerivedClass d = new DerivedClass();
            d.Execute("Func", 2);

            Console.ReadLine();
        }
    }
}

このサンプルにはコードの書式設定と名前付けにいくつかの癖がありますが、元のコードにできるだけ近づけるために、これはそのままにしておきます。

于 2012-05-23T13:51:47.187 に答える
4

これは、テンプレート メソッド patternの理想的な候補です。基本クラスは、Execute をオーバーライドする代わりにdoWork、派生クラスによって提供される必要があるメソッドを呼び出します。そうすれば、呼び出しを忘れることはなくbase.Execute、呼び出しの前後に基本クラスで何かを行うことができますdoWork

abstract class BaseClass 
{ 
    public BaseClass() { } 

    protected string methodName; 
    protected int noOfTimes; 
    public void Execute(string MethodName, int NoOfTimes) 
    { 
        this.methodName = MethodName; 
        this.noOfTimes = NoOfTimes;
        doWork();
    } 

    protected abstract void doWork(); // will be provided by derived classes
} 

class DerivedClass : BaseClass 
{ 
    public DerivedClass() : base() { } 

    protected override void doWork()
    {
        Console.WriteLine("Running {0}, {1} times", this.methodName, this.noOfTimes); 
    } 
} 

public class Program   
{   
    static void Main(string[] args) 
    { 
        DerivedClass d = new DerivedClass(); 
        d.Execute("Func", 2); 

        Console.ReadLine(); 
    } 
}

EDIT : Adam がコメントで正しく指摘しているように (感謝)、基本クラスを抽象化する必要はありません (基本クラスをインスタンス化する必要がない場合は便利です。サブクラスは の実装を提供しませんdoWork)。または、基本クラスでデフォルトの動作を指定することもできます。

class BaseClass 
{ 
    public BaseClass() { } 

    protected string methodName; 
    protected int noOfTimes; 
    public void Execute(string MethodName, int NoOfTimes) 
    { 
        this.methodName = MethodName; 
        this.noOfTimes = NoOfTimes;
        doWork();
    } 

    protected virtual void doWork() {
        // default behaviour, can be modified by subclasses
    }
} 
于 2012-05-23T13:57:14.593 に答える
1

また、この場合、既定のコンストラクターを明示的に呼び出す必要はありません。

public DerivedClass() : base() { }

のように定義すれば十分です。

public DerivedClass() { }

基本コンストラクターは、派生コンストラクターの前に自動的に呼び出されます。

元の質問については、Adam に同意しますが、彼は回答を完了するのが早かっただけです。:)

于 2012-05-23T13:55:44.750 に答える
1

まず、派生クラスでは、基本クラスで public または protected として定義されたすべてのメソッド、変数、およびプロパティにアクセスできます。これは、派生クラスで base.methodName を使用する必要がないことを意味します。

base は、派生クラスでの再定義の代わりに、基本クラスで定義されたメソッド/プロパティのバージョンにアクセスするために (通常は暗黙的な this の代わりに) 使用されます。ここではそうではありません。

さらに、あなたの場合、基本クラスと派生クラスで異なるシグネチャ(つまり、パラメーターの数や型が異なる)で Execute を定義しています。これは、それらが異なるため、別々に呼び出す必要があることを意味します。

そのバージョンで使用されていない場合でも、まったく同じパラメーターを使用して派生クラスでバージョンを定義する場合にのみ、Adam が指摘したように virtual と override を使用できます。ところで、ここでは、基本クラスで定義された Execute のバージョンを呼び出したいので、base を使用します。

于 2012-05-23T14:01:14.670 に答える