如果我打算覆盖所有方法,那么使用继承是不好的做法吗?

时间:2016-04-04 00:39:13

标签: java inheritance

考虑以下两个类:

class A {
    String _name;
    char _type;

    public A(String name, char type) {
        _name = name; _type = type;
    }

    public int method1() {
        do_something...;
    }

    public String method2() {
        make_something...;
    }
}

class B extends A {
    public B(String name) {
        super(name, 'a');
    }

    @Override
    public int method1() {
        do_something_else...;
    }

    @Override
    public String method2() {
        String answer = super.method2();
        answer += more_processing...;
    }
}

我在这里使用继承,因为这些类共享许多共同点。但是,因为我要覆盖超类中的每一个方法,在这里使用继承是个好主意吗?

5 个答案:

答案 0 :(得分:2)

这取决于具体情况。如果要使用该类的许多功能(属性和方法),则必须使用继承并覆盖需要更改的少数方法。如果您只使用几个功能并且需要覆盖几乎所有方法,那么最好创建一个新类。另一种情况可能是,如果该类的特定方法很难编码或具有非常重要的实现,那么它又取决于上下文。

答案 1 :(得分:1)

你必须问自己这个问题: B类是A类的子类吗?

只要您了解继承的用途,覆盖这些方法并不重要。 (即B类是A类的子类型,但做的事情略有不同)

答案 2 :(得分:1)

你要问的关键问题是:

" B是A?"

如果是这样,那么使用继承可能是一个好主意。

虽然您可能没有任何方法在这两个类中具有相同的实现,但将来可能会发生变化,因为您和代码库中的其他人可能会添加新方法。

你必须要问的另一个问题是,每种方法及其被覆盖的版本是否会因为它们的作用而不同,或仅仅因为它们如何表现?如果它是后者,那么再继承可能是要走的路。

在我工作的地方,我们认为最好的做法是尽可能多地使用接口(组合)而不是继承。这部分是因为一个类可以在Java中实现多个接口,但只能使用继承扩展一个类。还有其他原因,但我不想过于偏离主题。但是,如果你所写的课程之间的关系更多,那么他们只是拥有类似的成员,而不是拥有一个" is-a"关系,那么您可能想要考虑将这些共享成员(方法和字段)放在接口中而不是使用继承。

答案 3 :(得分:1)

只要您可以使用子类型A的实例替换超类型B的实例,就可以使用继承,而不会破坏任何内容。这也称为Liskov substitution principle

另一种hacky但仍然有效的继承情况是当你需要访问超类型A的其他无法访问的方法或属性时。在这种情况下,我更喜欢不直接让B扩展超类型A,而是使用扩展超类型B.ChildOfA的内部类A。这样可以防止B被用作A的实例,但这不合适。

一般情况下,您应该prefer composition over inheritance

回答你的问题:这不取决于你是否覆盖了所有内容,而是覆盖了你的子类可以或应该如何使用。

如果您覆盖AB的所有内容,并且您没有委托给超类型A,但这两种类型仍然可以像Liskov所定义的那样进行交换替换原则,那么你还有第三个选项:你可以声明一个公共超类型I并让两个类继承它。新引入的超类型I可以是接口或类。当然,只有拥有类A才有可能,因为您需要更改它以继承新的超类型I

答案 4 :(得分:1)

在这种情况下,B实际上并未从A继承任何内容,使用interface和{{1}的公共A可能更有意义以自己的方式实现。在进行这些类型的继承决策时,上下文很重要。

B

A:

public interface SomeInterface {

    public int method1();

    public String method2();

}

B:

public class A implements SomeInterface {