继承还是条件?

时间:2009-05-21 02:06:43

标签: language-agnostic oop

我听说有人说良好的设计涉及使用继承而不是使用if块乱丢你的代码。在什么情况下我们应该使用继承,什么时候条件块就好了?

8 个答案:

答案 0 :(得分:5)

这样的一次重构称为Replace Conditional With Polymorphism

我们实际上赞成composition over inheritance,但是......这里讨论的主题实在太宽泛了,但the book值得一读,可以帮助您入门。

答案 1 :(得分:2)

如果用于根据参数类型决定要做什么逻辑的块(或开关块)应该用多态替换。

如果程序中的新功能会导致您生成其他案例,或者块使用多态。

如果语句应该用于自然排序类型比较(<,>,==等)或检查某些东西是否为空。

答案 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块,在许多情况下,使用继承将使您的代码更具可扩展性和更强大。

答案 3 :(得分:1)

这是其中一个问题,虽然其他人可以提供指导,但任何特定情况的最终答案总是“,这取决于具体情况。”

能够为任何特定情况开发回答能力的最佳方式是获得经验:即实验。尝试两种方式,你可以合理地做到这一点。 (显然,你不想在必须改变一千行代码的情况下来回翻转。)哪种方法效果更好?哪种感觉对你好?为什么呢?

做到这一点,你很快就会达到不再需要一般建议的专业水平,人们开始问你在任何特定情况下如何知道该怎么做。 (您将无法解释它;这是专业知识性质的一部分。有关详细信息,请参阅The Dreyfus Model of Skill Acquisition

答案 4 :(得分: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为null的约定。 ToString必须检查OperatorType;那么任何其他方法都需要对它是什么算子起作用。

后一种方法最常出现在XML DOM实现中,其中XmlNode几乎是任何XML节点都可以包含的所有内容。它会造成一些非常令人困惑的情况:

  • 属性或文本节点如何具有ChildNodes?
  • 当文档只有一个时,它如何具有ChildNodes? (它不一定是一个集合)
  • 文档如何具有ParentNode?
  • 文档如何具有价值?

答案 5 :(得分: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);
    }

}

粗略的例子,但我希望你能抓住我的漂移......

答案 6 :(得分:0)

在我看来,这两者并不相互排斥。当我有2个或更多具有共同功能的类时,我通常使用继承。

答案 7 :(得分:0)