Расширение метода базового класса - PullRequest
13 голосов
/ 23 марта 2011

Я новичок в C # и пытаюсь понять основные понятия. Спасибо заранее за вашу помощь. У меня есть несколько примеров классов ниже (напечатаны в этом окне, поэтому могут быть некоторые ошибки) и у меня есть два вопроса:

  1. Можно ли вызвать метод производного класса, который выполняет код в методе базового класса с тем же именем, а затем выполняет код в методе производного класса? Каждый производный класс должен будет выполнить код базового класса для RunCheck, а затем выполнить специализированный код, специфичный для его класса. Я мог бы назвать RunCheck () как-то еще в базовом классе, а затем вызвать его, когда я вызываю RunCheck () производного класса, но затем я должен не забыть вызвать его в RunCheck () в производном классе. 1006 *

  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}
        }

Ответы [ 2 ]

26 голосов
/ 23 марта 2011

Просто вызовите base.RunCheck() в вашем DirectoryCheck классе:

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()

Я подозреваю, что вы действительно хотите, хотя это что-то вроде Non Virtual interface шаблон (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");
    }
}
3 голосов
/ 23 марта 2011

В производном классе вы можете вызвать метод в базовом классе, используя:

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()) и переопределить его при необходимости.

...