考虑以下两个类:
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...;
}
}
我在这里使用继承,因为这些类共享许多共同点。但是,因为我要覆盖超类中的每一个方法,在这里使用继承是个好主意吗?
答案 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。
回答你的问题:这不取决于你是否覆盖了所有内容,而是覆盖了你的子类可以或应该如何使用。
如果您覆盖A
中B
的所有内容,并且您没有委托给超类型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 {