【问题标题】:Extending a base class method扩展基类方法
【发布时间】:2011-03-23 03:21:16
【问题描述】:

我是 C# 新手,正在尝试理解基本概念。预先感谢您的帮助。我在下面有一些示例类(在此窗口中输入,因此可能存在一些错误)并且有两个问题:

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

【问题讨论】:

  • 在您的派生方法中,调用“super.RunCheck()”。它将调用父类方法。

标签: c# .net inheritance extension-methods


【解决方案1】:

只需在您的 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()

我怀疑你真正想要的是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");
    }
}

【讨论】:

  • 我会使用BaseClass abstract 并使用abstract CoreRun 而不是virtual
  • 或者另一种方式是将CheckerCore 类注入BaseCheck 类。
【解决方案2】:

在派生类中,您可以使用以下方式调用基类中的方法:

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

    // Followed by the implementation of the derived class
}

如 cmets 中所述,需要将基本方法声明为 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() 方法)并根据需要覆盖它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    相关资源
    最近更新 更多