2009-05-21 37 views
2

我聽過有人說好的設計涉及到使用繼承而不是亂拋垃圾的代碼。在什麼情況下我們應該使用繼承,並且當條件塊很好時?繼承或條件?

回答

2

通常,這是不好的面向對象編程的做法有如下代碼:

var chioce = PAINT_SCREEN_BLUE 

if (choice == PAINT_SCREEN_BLUE): 
    paintScreen(blue) 
else if (choice == PAINT_SCREEN_RED): 
    paintScreen(red) 
else if (choice == PAINT_SCREEN_GREEN): 
    paintScreen(green) 

上面可以利用多態性調用一些方法,該方法將執行在共同祖先的相關類別中抽象出的動作:

interface ScreenPainter: 
    function perform() 

class BlueScreenPainter implements ScreenPainter: 
    function perform(): 
     paintScreen(blue) 

... 

// The conditional block can be replaced with the following call: 
var choice = PAINT_SCREEN_BLUE 

ScreenPainter p = Painters.getPainter(choice) 
p.perform() 

然而,這種做法絕對不應該適用於所有條件語句然而,當涉及到長switch塊或if-elseif-else塊,在許多情況下,繼承的使用將會使你的代碼更具擴展性和更強大的。

0

這裏是我跑進了一天

PHP是我的首選語言

class Cache { 

    public function __construct($resource) { 

    // if statement to determine from type if it is a file, url or string. instead, change it to accept a string 

    } 

} 

或者......它可能的被延長

class cacheURL extends Cache { 

    public function __construct($url) { 

     $string = file_get_contents($url); 

     parent::__construct($string); 
    } 

} 

粗糙的例子,但我希望你趕上我的漂移....

0

在我看來,兩者並不相互排斥。當我有2個或更多具有通用功能的類時,我通常會使用繼承。

2

如果用於根據參數類型決定執行什麼邏輯的塊(或開關塊)應該用多態性替換。

如果程序中的新功能會導致您創建其他案例或使用多態性塊。

如果語句應該用於自然排序類型比較(<,>,==等)或檢查是否爲空。

0

當某些條件正在檢查不斷檢查的對象的內在物體(如狀態或類型)時,繼承效果會更好。在這個例子中,它是一個數學表達式樹的運算符。像加法這樣的運算符在加號前後有一個表達式(infix notation),所以我將它們稱爲左和右,因爲它表示爲樹。還有像連字符這樣的一元操作符可以否定值,但它只有一個孩子表達式。

使用繼承意味着類型(簡化爲一元對比二進制)被計入繼承:

class Operator 
{ 
    abstract string ToString(); 
} 
class UnaryOperator : Operator 
{ 
    Expression Expression { get; } 
    override string ToString() {...} 
} 
class BinaryOperator : Operator 
{ 
    Expression LeftExpression { get; } 
    Expression RightExpression { get; } 
} 
class AdditionOperator : BinaryOperator 
{ 
    override string ToString() 
    { 
     return this.LeftExpression.ToString() + "+" + this.RightExpression.ToString(); 
    } 
} 

至於反對:

class Operator 
{ 
    Expression LeftExpression { get; } 
    Expression RightExpression { get; } 

    OperatorType Type { get; } 

    string ToString() 
    { 
     switch(this.Type) 
     { 
      case OperatorType.Addition: 
       return this.LeftExpression.ToString() + "+" + this.RightExpression.ToString(); 
      case OperatorType.Negation: 
       return "-" + this.LeftExpression.ToString(); 
      case ...: 
     } 
    } 
} 
enum OperatorType 
{ 
    // Unary operators 
    Negation, 

    // Binary operators 
    Addition, 
    Subtraction, 
    Multiplication 
} 

這裏你一元運算符沒有左,右的表情,只是一種表達。這意味着你必須引入使用Left和Right爲空的約定。 ToString將不得不檢查OperatorType;那麼其他任何方法都需要根據它是什麼操作符來操作。

後一種方法最常見於XML DOM實現,其中XmlNode幾乎是任何XML節點可能包含的東西...永遠。它使一些非常混亂的情況:

  • 如何可以屬性或文本節點有ChildNodes?
  • 如果一個文檔只有一個文檔可以有一個ChildNodes,它該如何處理? (它不一定是一個集合)
  • 文檔如何具有ParentNode?
  • 文件如何具有價值?
  • 等等
1

這是那些問題,雖然其他人可以提供指引,針對任何特定情形最終的答案永遠是,一個「這要看情況。」

能夠開發回答任何特定情況的能力的最佳方式是獲得經驗:即實驗。嘗試兩種方式,你可以合理地做到這一點。 (很明顯,你不想在需要修改一千行代碼的情況下來回翻轉)。哪個更好?你覺得更好嗎?爲什麼?

這樣做夠了,你很快就會達到不再需要一般建議的專業水平,人們開始問你如何知道在特定情況下要做什麼。 (您將無法解釋它;這是專業性質的一部分。有關更多詳細信息,請參見The Dreyfus Model of Skill Acquisition