2011-03-23 129 views
10

我是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} 
     } 
+0

在你的派生方法中,调用'super.RunCheck()'。它会调用父类的方法。 – Doodloo 2011-03-23 03:24:24

回答

22

只需拨打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"); 
    } 
} 
+0

我会使'BaseClass''抽象'并使用'抽象''CoreRun'而不是'virtual'。 – Aron 2014-03-06 02:24:10

+0

,或者另一种方法是将“CheckerCore”类注入到“BaseCheck”类中。 – Aron 2014-03-06 02:25:20

3

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

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

或者你可以有你的类的打印输出方法的一部分(甚至使用现有ToString()方法),并覆盖它的要求。

+0

如果您提到基类方法必须是虚拟的,则为+1。 – Kimberly 2011-03-23 03:32:09

+0

谢谢 - 它已被添加 – 2011-03-23 03:34:24