通过扩展具体父类来拥有抽象子类的目的是什么?

6
有时候,我会遇到一些如下所示的类设计。
abstract class animal {
    public abstract void speak();
}

class dog extends animal {

    @Override
    public void speak() {
        // Do something.
    }

}

abstract class abstract_dog extends dog {
    @Override
    public abstract void speak();
}

我想知道,为什么要有一个abstract_dog类?为什么我们要将非抽象的speak方法再次转换为抽象的speak方法?

这是为了提供一个基础类,其他狗的类可以继承并实现自己的具体方法。通过使用抽象方法,我们可以确保所有子类都实现了相同的方法,并且它们都遵循相同的方法签名。


注意:如果您控制类层次结构,更好的方法要么是完全消除具体的狗类,要么是使其成为抽象狗的子类。最好将非叶类设为抽象。 - Andy Thomas
2个回答

4

如果您想创建一个基类来强制用户重写 speak ,但同时继承 Dog,可以这样做。


虽然你的回答在技术上是正确的,但如果我在审查过程中遇到这种情况,我仍然会认为这是一种代码异味。(仍然+1) - nfechner
@nfechner:这完全取决于具体情况。我认为在5年以上的开发中,我只需要做过一次这样的事情。 - SLaks
+1 的原因很简单,尽管您的答案(以及问题)缺乏一些现实情况。 - Oben Sonne
@SLaks,一个好的、理智的、有效的代码异味依然是一个,正如你仍然记得你曾经需要这样做一样。我认为,我们应该把它当作一个hack来对待并承认它,并在顶部加上一个大的免责声明:“孩子们:别在家里这样做”。 - nfechner

0

我同意SLaks的观点,认为这将是一个真实的生活情境:

abstract class animal {
    public abstract void speak();
}

class dog extends animal {

    @Override
    public void speak() {
        // Dog says 'bark'
    }

}

abstract class abstract_dog extends dog {
    @Override
    public abstract void speak();
}

class poodle extends abstract_dog {
    @Override
    public void speak() {
        // poodle says 'yip yip'
    }
}

class great_dane extends abstract_dog {
    @Override
    public void speak() {
        // great dane says 'ruff ruff'
    }
}

我认为你会在以下情况下使用它:当你想要创建一个新的子类来实现speak方法时,而dog类可能有其他新的方法需要实现,但新的子类不需要实现这些方法。
了解更多关于你具体情况的信息将有助于确定是否有更好的设计方案适用于此场景。


但在这个例子中,您也可以跳过abstract_dog。 - Buhb
@Buhb,这是真的,这个设计存在潜在问题。 - rosscj2533

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接