web-dev-qa-db-ja.com

基本クラスメソッドの拡張

私はC#を初めて使用し、基本的な概念を理解しようとしています。よろしくお願いします。以下にいくつかのサンプルクラスがあり(このウィンドウに入力されているため、エラーが発生する可能性があります)、2つの質問があります。

  1. 同じ名前の基本クラスメソッドのコードを実行してから、派生クラスメソッドのコードを実行する派生クラスメソッドを呼び出すことは可能ですか?すべての派生クラスは、RunCheckの基本クラスコードを実行してから、そのクラスに固有の特殊なコードを実行する必要があります。基本クラスでRunCheck()に別の名前を付けて、派生クラスのRunCheck()を呼び出すときに呼び出すこともできますが、派生クラスのRunCheck()で呼び出すことを忘れないでください。

  2. Program.csで、渡した派生クラスにないフィールドにある場合、空白の値ですべてのフィールドを出力したいと思います。何を渡しますか?

これが私のコードです:

  class baseCheck
  {
      public DateTime StartTime { get; set; }
      public DateTime LastRun { get; set; }
      public int Runs { get; set; }
      //Others

      public void RunCheck()
      {
         if (Started != null)
           started = DateTime.Now;

         LastRun = DateTime.Now;

         Runs++;
      }
    }

    class FileCheck : baseCheck
    {
       public string FileName { get; set; }

       public void RunCheck()
       {
           //I want all the code in the base class to run plus
           //any code I put here when calling this class method

        }
    }
    class DirectoryCheck : baseCheck
    {
       public string DirectoryName { get; set; }

       public void RunCheck()
       {
           //I want all the code in the base class to run plus
           //any code I put here when calling this class method

        }
    }

        //Program.cs
        static void Main()
        {
           //Create derived class - either DirectoryCheck or FileCheck
           //depending on what the user chooses.

            if (Console.ReadLine()=="F")
            {
                FileCheck c = new FileCheck();  
            }
            else
            {
                DirectoryCheck c = new DirectoryCheck();
            }

            PrintOutput(c);

        }
        private void PrintOut(What do I put here?)
        {
           Console.WriteLine("Started: {0}",f.StartTime)
           Console.WriteLine("Directory: {0}", f.DirectoryName)
           Console.WriteLine("File: {0}", f.FileName}
        }
16
NewToCSharp

DirectoryCheckクラスでbase.RunCheck()を呼び出すだけです。

_public class DirectoryCheck : baseCheck
{
    public string DirectoryName { get; set; }

    public void RunCheck()
    {
        //I want all the code in the base class to run plus
        //any code I put here when calling this class method
        base.RunCheck();
        Console.WriteLine("From DirectoryCheck");
    }
}
_

また、現在の実装では、基本クラスのRunCheck()メソッドを非表示にしています-実際にオーバーライドする必要があります-これにより、基本クラスのメソッドシグネチャが次のように変更されます。

_    public virtual void RunCheck()
_

および派生クラスで

_    public override void RunCheck()
_

非仮想インターフェース パターン(NVI)-保護された仮想メソッドを基本クラスで公開します。子クラスはオーバーライドできますが、基本にパブリックメソッドがあります。そのメソッドを内部で実際に呼び出しているクラス-このアプローチにより、その呼び出しの前後に実行していることを拡張できます。

あなたの例では、これは次のようになります。

_class BaseCheck
{
    private DateTime Started { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime LastRun { get; set; }
    public int Runs { get; set; }
    //Others

    public void RunCheck()
    {
        if (Started != null)
            Started = DateTime.Now;

        LastRun = DateTime.Now;
        Runs++;
        CoreRun();
    }

    protected virtual void CoreRun()
    {

    }
}


public class DirectoryCheck : BaseCheck
{
    public string DirectoryName { get; set; }

    protected override void CoreRun()
    {
        //I want all the code in the base class to run plus
        //any code I put here when calling this class method
        Console.WriteLine("From DirectoryCheck");
    }
}
_
29
BrokenGlass

派生クラスでは、以下を使用して基本クラスのメソッドを呼び出すことができます。

_public override void RunCheck()
{
    base.RunCheck();

    // Followed by the implementation of the derived class
}
_

コメントで述べたように、オーバーライドを許可するには、基本メソッドをvirtualとして宣言する必要があります。

_public virtual void RunCheck() { ... }
_

PrintOut()メソッドには魔法の方法はありませんが、基本クラスをパラメーターとして受け取り、型をテストすることができます。

_private void PrintOut(baseCheck f)
{
   Console.WriteLine("Started: {0}", f.StartTime)
   Console.WriteLine("Directory: {0}", f.DirectoryName)

   if (check is FileCheck)
   {
       Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
   }
}
_

または、オーバーロードを使用できます。

_private void PrintOut(baseCheck f)
{
   Console.WriteLine("Started: {0}", f.StartTime)
   Console.WriteLine("Directory: {0}", f.DirectoryName)
}

private void PrintOut(FileCheck f)
{
    PrintOut((baseCheck)f);

    Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}
_

または、PrintOutメソッドをクラスの一部にして(おそらく既存のToString()メソッドを使用することもできます)、必要に応じてオーバーライドすることもできます。

3
Xavier Poinas