2016-09-19 61 views
0

所以,我有下面的方法,這是abstract類的一部分,基本上是一個二維數組的字符。我打算有幾個稍有不同行爲的子類,知道如何以不同的方式填充自己。C#:如何構造這個方法,這意味着被覆蓋

有問題的方法應該插入一個字符串到數組中。爲了避免溢出錯誤,我需要檢查數組中是否有空間。檢查這個空間是否足夠簡單,但這是問題開始的地方。

如果沒有足夠的空間,我希望每個子類定義它將如何處理該行爲。 (例如,一些子類將在開始時重新開始,其他一些將不做任何事情並停止插入字符,其他字符將刪除頂部行,將所有內容向上移動,並將其寫入底部的新空白行中,其他則會放棄並使程序崩潰等)

請參閱下面的代碼中的註釋。我想我想override的實現,但有沒有辦法我可以重寫else分支,還是我必須將整個方法移入子類?

IsEnoughRoom是類中的私有方法。)

internal void InsertString(string stringToInsert, int xStart, int yStart) 
{ 
    char[] charsToInsert = stringToInsert.ToCharArray(); 
    int currentXPosition = xStart; 
    int currentYPosition = yStart; 

    // For each character in the array of charsToInsert, 
    for (int i = 0; i < charsToInsert.Length; i++) 
    { 
     // Check if there is enough room... 
     if(isEnoughRoom(xStart, yStart, charsToInsert)) 
     { 
      SetCharAt(currentXPosition, currentYPosition, charsToInsert[i]); 

      if (currentXPosition < xSize - 1) 
      { 
       currentXPosition++; 
      } 
      else 
      { 
       currentXPosition = 0; 
       currentYPosition++; 
      } 
     } 
     else 
     { 
      //TODO: What do we do if there isn't enough room? 
     } 
} 
+5

爲什麼不在「else」分支中調用虛擬或抽象方法?目前還不清楚你如何「從頭開始」重點介紹你......我的猜測是你不能*真的*表達你想在其他分支中做的所有事情...... –

+0

@JonSkeet糾正我如果我錯了,但如果我這樣做,我將無法訪問方法中的字段,對嗎?我的意思是,我無法將'currentYPosition'設置爲'0'並從頭開始?或者我在這裏錯過了一個概念? – Airhead

+0

那麼你*可能*通過引用方法潛在地傳遞變量......或使用返回值。 (或者你可能希望把所有這些封裝成一個單一的對象......)但是這就是爲了顯示那個'else'分支的主體在不同的情況下會是什麼樣子這麼有幫助...... –

回答

1

有一個可能的替代方法在您的抽象類的方法是virtual,它可以返回一個枚舉值,以確定究竟是什麼結果,並讓來電者休息一下。整個調用者可以是派生類。

讓我們在行動中看到此解決方案:

public enum CharInsertionResult 
{ 
    Success, 
    NoRoom 
} 

public abstract class CharInserter 
{ 
    internal virtual CharInsertionResult InsertString(string stringToInsert, int xStart, int yStart) 
    { 
     char[] charsToInsert = stringToInsert.ToCharArray(); 
     int currentXPosition = xStart; 
     int currentYPosition = yStart; 

     // For each character in the array of charsToInsert, 
     for (int i = 0; i < charsToInsert.Length; i++) 
     { 
      // Check if there is enough room... 
      if(isEnoughRoom(xStart, yStart, charsToInsert)) 
      { 
       SetCharAt(currentXPosition, currentYPosition, charsToInsert[i]); 

       if (currentXPosition < xSize - 1) 
       { 
        currentXPosition++; 
       } 
       else 
       { 
        currentXPosition = 0; 
        currentYPosition++; 
       } 

       return CharInsertionResult.Success 
      } 
      else 
      { 
       return CharInsertionResult.NoRoom; 
      } 
     } 
    } 
} 

現在派生類可以重寫抽象類的實現提供瞭解決方案,以CharInsertionResult.NoRoom情況:

public class SpecializedCharInserter : CharInserter 
{ 
    internal override CharInsertionResult InsertString(string stringToInsert, int xStart, int yStart) 
    { 
      CharInsertionResult result = base.InsertString(stringToInsert, xStart, yStart); 

      switch(result) 
      { 
       case CharInsertionResult.NoRoom: 
         // Do stuff here to handle this scenario 
         break; 

       default: 
         return result; 
      } 
    } 
} 

恕我直言,我認爲這是一個好的設計,因爲如果你不想處理NoRoom的情況,你不需要重寫一個方法,否則,你在派生類中有一個可擴展點。

+0

但是我一次只能繼承一個類,並且包含InsertString的類還有其他方法來履行其在CharInserter類中不合適的責任。或者我誤解了? – Airhead

+0

@HCBPshenanigans如果一個給定的子類需要這些方法,那麼你需要使它們成爲'protected'。我錯了嗎? –

+0

我重讀你的答案,現在就更好地理解它。事實證明,我只需要從筆記本電腦中走開一會兒,在回到它之前想想其他事情。現在我知道你的意思了,我認爲這是一個好的方法。謝謝! – Airhead