是否允许扩展Shape类?

Enr*_*ico 1 java inheritance geometry javafx shapes

我有多个从 Shape 类扩展而来的几何图形,如下所示:

public class ExtendedLine extends Line {

  private String attribute;

  // more attributes and methods
}
Run Code Online (Sandbox Code Playgroud)
public class ExtendedCircle extends Circle {

  private String attribute;

  // more attributes and methods
}
Run Code Online (Sandbox Code Playgroud)

现在,为了一次访问所有几何图形,我定义了一个超类,它扩展了 Shape 并包含 ExtendedLine 和 ExtendedCircle 共有的所有属性和方法。这为我节省了很多冗余代码。

public class Geometry extends Shape {
  
  private String attribute;
  
  // more attributes and methods
}
Run Code Online (Sandbox Code Playgroud)
public class ExtendedLine extends Geometry {
}
Run Code Online (Sandbox Code Playgroud)
public class ExtendedCircle extends Geometry {
}
Run Code Online (Sandbox Code Playgroud)

是否允许/良好的做法来扩展 Shape 类?

Sla*_*law 6

我猜你说的是班级javafx.scene.shape.Shape。如果这是正确的,那么文档1表示您不应该扩展该类:

应用程序不应直接扩展 Shape 类。这样做可能会导致抛出 UnsupportedOperationException。

但是,该类不是最终类,它有一个公共构造函数,并且没有包私有抽象方法(您无法覆盖这些方法)。因此,实际上没有什么可以阻止您扩展Shape和编译代码,但它可能无法在运行时正常工作1。我建议您注意文档并且不要扩展它。

请注意其他类也有类似的文档(例如,javafx.scene.Node1。如果今天编写 JavaFX,这些类可能会是sealed,任何可扩展子类都被标记为non-sealed。请参阅JEP 409:密封类

扩展还有另一个问题Shape。当您扩展Line时,您的子类a Line,只是添加了属性和方法。但是,当您的例如ExtendedLine类扩展Shape(通过您的Geometry类)时,它就不再是Line. 您无法将其添加到场景图中并期望绘制一条线。这意味着要么自己画线,要么让子类包装一个Line您可以访问的实例;但无论哪种情况,子类化Shape首先有什么意义呢?


1.出于所有意图和目的,您应该将文档解释为将UnsupportedOperationException 抛出,而不仅仅是可能被抛出。我只能假设他们是这样措辞的,因为只有当您将直接子类的实例添加到场景图中(至少在我的测试中)时才会引发异常,但并不是每个应用程序都保证会尝试这样做。

我用 、 、 和 的直接子类对此javafx.scene.Node进行javafx.scene.LightBasejavafx.scene.shape.Shape测试javafx.scene.shape.Shape3DUnsupportedOperationException当添加到场景图中时,所有这些都会导致抛出。可能还有其他课程存在相同的“问题”,但这些是我目前所知道的。