2011-03-23 131 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