【问题标题】:Java: Disallow certain methods from extended class?Java:不允许扩展类中的某些方法?
【发布时间】:2012-03-29 19:52:30
【问题描述】:

我创建了一个扩展 Point2D.DoubleVector2D 类。

Vector2D 有两个字段:幅度和方向。 Point2D.Double 的扩展还允许向量存储起始位置。

我喜欢这样做的能力:

Vector2D myVector = new Vector2D(50, 50);  // instantiated without direction or magnitude
Point2D.Double myPoint = new Point2D.Double(myVector.getLocation());

但是,我不想这样做:

Point2D.Double myPoint = myVector;

还有这个:

Point2D.Double myPoint.setLocation(myVector);

因为这两个操作都将myVector 视为只是 Point2D.Double

我知道 Java 不允许覆盖或重载运算符,因此第一个不受欢迎的情况似乎特别难以消除。我也知道我可以用一个空的方法体覆盖.setLocation()(以防止它被使用),但这并不是一个很好的解决方案。

有没有办法禁止 Vector2D 存在于Point2D.Double 中的方法或运算符?

【问题讨论】:

  • 组合优于继承。
  • 如果您通过 Vector 扩展 Point2D 的唯一原因是存储起始位置,为什么不让 2D 点成为 Vector 的成员?
  • 嗯,我也喜欢.distance()等方法。我想我可以简单地编写自己的方法,使用私有 Point2D 字段进行计算。
  • Math.hypot() 很方便。

标签: java inheritance overriding overloading extends


【解决方案1】:

我没有在这里看到问题。如果您希望 Vector2D 成为 Point2D.Double 的子类,那么您明确声明它 IS 是 Point2D.Double。如果客户端想要将其用作 Point2D.Double 则允许且完全合法。

听起来您想要完成的是将子类化为代码重用系统,而不是真正的 is-a 关系。这通常被认为是一种反模式。

要么接受客户端可以这样做(即使你不喜欢它),要么改用组合对象。

【讨论】:

    【解决方案2】:

    不,没有办法禁止这样做。

    但是,您可以尝试使用包含特定功能的 Vector 字段的非继承方法。一个缺点是这将不允许您适应您提到的以下功能:

    Vector2D myVector = new Vector2D(50, 50);  // instantiated without direction or magnitude
    Point2D.Double myPoint = new Point2D.Double(myVector.getLocation());
    

    不确定是否有干净的方法来处理这个问题。我想知道您需要这种行为的用例是什么。

    【讨论】:

      【解决方案3】:

      这在 类型级别 是不可能的,因为 Java 的子类型系统如何工作以及 Liskov substitution principle。 (还有其他语言,例如Eiffel确实允许这种模式!)

      Liskov 的 [behavioral] 子类型概念定义了 ... 如果 S 是 T 的子类型,则程序中 T 类型的对象可以在不改变 [那个程序] 的情况下被 S 类型的对象替换 em> ....

      如果使用继承最好的是抛出一个"Not Supported Exception",或者,正如所指出的,什么都不做。 (请注意,这实际上违反了将 行为正确性作为要求的 LSP!)

      如果使用了多个谨慎的接口——但它们不在这里——那么就有可能选择'n'选择要实现的接口(这可以通过组合来完成)。但是,对于组合(或其他不相关的类型),不能使用自定义 Vector2D 作为Point2D.Double,因此 Java 显示了与子类型绑定是多么容易;-) 我现在倾向于多个专门的接口。

      如果显式转换是可以接受的,那么Vector2D.fromPoint2D(...)Vector2D.toPoint2D(...) 是一种可以接受的方法...

      编码愉快。

      【讨论】:

        猜你喜欢
        • 2011-08-11
        • 1970-01-01
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-31
        • 2019-08-21
        • 1970-01-01
        相关资源
        最近更新 更多