如何确定a-a或instanceof关系在特定情况下是否合适?

时间:2013-05-07 23:48:31

标签: java object inheritance coding-style object-oriented-analysis

好吧,现在这已经发生在我身上很多次,所以我不妨问社区。我经常遇到一个问题,决定是将某个东西声明为实例还是作为一个继承(并声明一个子类的实例),这是合适的。

例如,

  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;
    }

现在,如果staticBaseStationBaseStation,其中(x,y)未发生变化且dynamicBaseStationBaseStation,其(x,y)会发生变化,我不能只是将静态和动态BaseStations声明为单独的对象dynamicBaseStation每当它的位置发生变化时调用setXsetY?但我觉得这样做会违反OO原则。

所以基本上我如何决定是否在工作时使用继承?

3 个答案:

答案 0 :(得分:1)

这取决于你如何定义类的合同。

a)如果指定BaseStation值可以更改(或者您没有指定它不能更改),则可以使用该类的两个实例。

b)如果您指定BaseStation值不能更改,那么您不仅不能使用同一类的两个实例来进行该用法,而且甚至无法扩展BaseStation来获取{{1} (因为子类会违反超类合同)。您可能需要设置一个通用界面。

您的合同越严格,类的可重用性就越低。但是,由于更好地定义了类的行为,您可以使用其属性来简化使用类/避免错误(DynamicBaseStation方法可以让您更改a的值,{ {1}}方法迫使你使用另一个类,最好是兄弟姐妹。)

在这个具体的类中,我将定义StaticBase而不指定它不能被移动,并创建一个b来完善父契约(但不会与之相矛盾),但要确定它不能改变它的位置。通常,程序是在继承(特化)时增加限制。

无论如何,这是一个经验法则。可能还有其他动机迫使您以某种方式定义合同;重要的是,在扩展课程时不要破坏。

答案 1 :(得分:0)

我认为在这种情况下接口会更合适,因为派生的StaticBaseStation不会使用任何超类方法,但是你可能希望能够在某些情况下使用任何一种类型。

例如,如果这些类共享一个接口,您可以编写接受接口作为参数的方法,这将允许您为这两种类型重用这些方法。

答案 2 :(得分:0)

当派生类可以互相替换时,您可以使用继承......消费者在使用基类时不需要了解衍生产品。

你的例子违反了Liskov Substitution原则。如果DynamicBaseStation在预期使用StaticBaseStation的上下文中使用,则可能会出现错误(意外行为)。

查看Liskov替换原则here或直接here

无论如何,我会尽可能地赞成合成而不是继承。继承可以让你陷入麻烦,因为组合可以 - 通常 - 几乎没有什么害处,但仍然允许你改变抽象背后的实现细节。请参阅此question/answer