理解继承

时间:2010-05-31 18:37:58

标签: design-patterns inheritance

我现在已经绞尽脑汁继承遗传一段时间,但我仍然无法完全绕过它。

例如,前几天我正在考虑将无懈可击的人与可怜的人联系起来。我们先来定义两个:

  • 绝对正确的人:一个永远不会犯错误的人。它的 do_task()方法永远不会抛出异常
  • 易受伤害的人:偶尔犯错误的人。它的 do_task()方法可能偶尔抛出ErrorProcessingRequest异常

问题是: 是一个绝对正确的人类,一个容易犯错的人或者是一个容易犯错的人类AN无懈可击的人吗?

我收到的非常好的答案是问题的形式(我喜欢这些,因为它给了我规则来回答我可能有的未来问题)。

“你能否通过一个绝对正确的人类,预计会出现一个容易犯错的人类,或者你可以通过一个容易犯错的人类,这是一个可靠的人类吗?”

很明显,你可以通过一个绝对正确的人类,在这个人类可以预见到一个错误的人,但不是相反。我想这回答了我的问题。

然而,“一个绝对正确的人是一个易犯错的人”仍然感觉很有趣。当他们说出来时,还有其他人感到不安吗?说出继承树就好像用简单的英语读出命题演算中的陈述(if / then蕴涵连词并不意味着与英语口语相同)。还有其他人有同感吗?

5 个答案:

答案 0 :(得分:8)

  

“很明显你可以通过   一个绝对可靠的人类   人是预期的,但不是另一个   “#/ p>

在某种情况下,这只是一个正确的假设。以这种方式分解:

  1. 如果您的系统逻辑需要传递 会犯错误的人,那么这是不正确的。

  2. 如果系统的逻辑不关心人类会做什么,那么这个 是正确的。

  3. 换句话说,完全取决于系统的要求来确定问题"IS an infallible human A fallible human OR IS a fallible human AN infallible human?"的答案。

    逻辑对象已被拟人化的事实可能比任何东西都更令人困惑,因为看起来你的混乱源于哲学的立场而不是逻辑的立场。用“对象X”和“对象Y”取代“绝对可靠的人”和“易犯错的人”,它可以为你清除思路。

答案 1 :(得分:5)

在这种情况下,我会说父类是答案:FallibleHuman继承自Human,InFallibleHuman也是如此。

答案 2 :(得分:2)

继承的主要目的是提供通用功能并描述类之间的共性。我建议你对这两个人的特征(绝对可靠和易犯错误)的描述会分散注意力并造成混乱。

人类的“常见”是什么?所有人都有一个公共的“do_task()”方法和一个私有/受保护的“do_something()”方法。所以我们描述它是一个名为“人类”的超级类

public abstract class Human
{
    // describes commonality
    public abstract void do_task();

    // provides common functionality
    protected virtual void do_something()
    {
        throw new Exception("I made a mistake");
    }
}

现在“继承”类为do_task()方法实现了自己的特定逻辑,但它们共享受保护的do_something()方法的通用功能

public class InfallibleHuman : Human
{
    public override void do_task()
    {
        try
        {
            do_something();
        }
        catch
        {
            // never throw an exception
            // because I never make mistakes
        }
    }   
}

public class FallibleHuman : Human
{
    public override void do_task()
    {
        do_something();
        // always throw an exception if
        // something goes wrong because I'm accountable
        // for my own actions
    }
}

现在,我们已经使用继承来描述人类之间的共性并提供默认的常见实现,但是子类版本添加了特定的行为,我们使用“Fallible”和“Infallible”这个词来描述,与继承无关。

现在,如果你有使用人类的东西,它会接受任何人,你可以使用InfallibleHuman或FallibleHuman。

public void ImPrettyTolerantOfMistakes()
{
    try
    {
        Human anyHumanWillDo = new FallibleHuman();
        anyHumanWillDo.do_task();
        Human anotherHuman = new InfallibleHuman();
        anotherHuman.do_task();
    }
    catch
    {
        // I'll take care of a human
        // making a mistake
    }
}

但是如果你使用的东西不能容忍人类出错,你就会使用一个完美的人......

public void ImIntolerantOfHumansWhoMakeMistakes()
{
    InfallibleHuman onlyAPerfectHumanWillDo = new InfallibleHuman();
    onlyAPerfectHumanWillDo.do_task();

    // if this guy fails, I'm dead meat
}

我希望事情能为你解决一些问题。

答案 3 :(得分:0)

我同意Daenyth ......

因为曾经永远不会犯错误,而且从逻辑上说这就是答案。

合同方式如果一个方法期望一个人不会犯错误,那么它就不能得到一个,并且如果它期望一个人做到这一点,就不能得到一个没有错误的人。

人类的基类,可能会或可能不会犯错误。

答案 4 :(得分:0)

在特殊情况下通常会抛出例外情况。如果一个易犯错误的人的观点是它会犯错误,为什么会有例外呢?

至于手头的问题,我会说他们不能相互继承,而是来自父类人类。它们都是人类。