例如,
public class BaseStation{
public BaseStation( int x, int y ){
this.x = x;
this.y = y;
}
public void setX( int x ){ this.x = x; }
public void setY( int y ){ this.y = y; }
private int x;
private int y;
}
现在,如果staticBaseStation
是BaseStation
,其中(x,y)
未发生变化且dynamicBaseStation
是BaseStation
,其(x,y)
会发生变化,我不能只是将静态和动态BaseStations声明为单独的对象dynamicBaseStation
每当它的位置发生变化时调用setX
,setY
?但我觉得这样做会违反OO原则。
所以基本上我如何决定是否在工作时使用继承?
答案 0 :(得分:1)
这取决于你如何定义类的合同。
a)如果指定BaseStation
值可以更改(或者您没有指定它不能更改),则可以使用该类的两个实例。
b)如果您指定BaseStation
值不能更改,那么您不仅不能使用同一类的两个实例来进行该用法,而且甚至无法扩展BaseStation
来获取{{1} (因为子类会违反超类合同)。您可能需要设置一个通用界面。
您的合同越严格,类的可重用性就越低。但是,由于更好地定义了类的行为,您可以使用其属性来简化使用类/避免错误(DynamicBaseStation
方法可以让您更改a
的值,{ {1}}方法迫使你使用另一个类,最好是兄弟姐妹。)
在这个具体的类中,我将定义StaticBase
而不指定它不能被移动,并创建一个b
来完善父契约(但不会与之相矛盾),但要确定它不能改变它的位置。通常,程序是在继承(特化)时增加限制。
无论如何,这是一个经验法则。可能还有其他动机迫使您以某种方式定义合同;重要的是,在扩展课程时不要破坏。
答案 1 :(得分:0)
我认为在这种情况下接口会更合适,因为派生的StaticBaseStation
不会使用任何超类方法,但是你可能希望能够在某些情况下使用任何一种类型。
例如,如果这些类共享一个接口,您可以编写接受接口作为参数的方法,这将允许您为这两种类型重用这些方法。
答案 2 :(得分:0)
当派生类可以互相替换时,您可以使用继承......消费者在使用基类时不需要了解衍生产品。
你的例子违反了Liskov Substitution原则。如果DynamicBaseStation在预期使用StaticBaseStation的上下文中使用,则可能会出现错误(意外行为)。
无论如何,我会尽可能地赞成合成而不是继承。继承可以让你陷入麻烦,因为组合可以 - 通常 - 几乎没有什么害处,但仍然允许你改变抽象背后的实现细节。请参阅此question/answer。