Issue
I have multiple geometries which extends from a Shape class like this:
public class ExtendedLine extends Line {
private String attribute;
// more attributes and methods
}
public class ExtendedCircle extends Circle {
private String attribute;
// more attributes and methods
}
Now, to access all geometries at once, I defined a super class which extends Shape and contains all attributes and methods which the ExtendedLine and ExtendedCircle have in common. This saves me a lot of redundant code.
public class Geometry extends Shape {
private String attribute;
// more attributes and methods
}
public class ExtendedLine extends Geometry {
}
public class ExtendedCircle extends Geometry {
}
Is it allowed / good practice to extend the Shape class?
Solution
I assume you're talking about the javafx.scene.shape.Shape
class. If that's correct, then the documentation1 says that you should not extend that class:
An application should not extend the Shape class directly. Doing so may lead to an UnsupportedOperationException being thrown.
However, the class is not final, it has a public constructor, and it has no package-private abstract methods (which you would not be able to override). So, there's nothing physically stopping you from extending Shape
and compiling the code, but it may not work properly at run-time1. I would suggest you heed the documentation and don't extend it.
Note other classes have similar documentation (e.g., javafx.scene.Node
)1. Likely these classes, if JavaFX were written today, would be sealed
, with any extendable subclasses being marked non-sealed
. See JEP 409: Sealed Classes.
There's another problem with extending Shape
. When you extend Line
then your subclass is a Line
, just with the added attributes and methods. But when your e.g., ExtendedLine
class extends Shape
(via your Geometry
class), then it is no longer a Line
. You can't add it to your scene graph and expect a line to be drawn. That means either drawing the line yourself, or having the subclass wrap a Line
instance that you can access; but in either case, what was the point of subclassing Shape
in the first place then?
1. For all intents and purposes, you should interpret the documentation as if it said an UnsupportedOperationException
will be thrown, not just may be thrown. I can only assume they worded it that way because the exception is only thrown when you add an instance of the direct subclass to the scene graph (at least in my tests), but not every application is guaranteed to attempt that.
I tested this with direct subclasses of javafx.scene.Node
, javafx.scene.LightBase
, javafx.scene.shape.Shape
, and javafx.scene.shape.Shape3D
. All of them resulted in an UnsupportedOperationException
being thrown when added to the scene graph. There may be other classes with the same "problem", but those are the ones I'm aware of currently.
Answered By - Slaw
Answer Checked By - Candace Johnson (JavaFixing Volunteer)