I think this proposal makes a lot of sense. Having the trait interfaces inner classes of Trait clearly narrows down semantics. "Trait" might be too generic, maybe FxTrait or something like that? Just a thought.
What other traits/properties should we include? Converting https://github.com/openjdk/jfx/pull/1215 to draft until this discussion comes to a resolution. -andy From: openjfx-dev <openjfx-dev-r...@openjdk.org> on behalf of Michael Strauß <michaelstr...@gmail.com> Date: Saturday, September 2, 2023 at 15:09 To: openjfx-dev <openjfx-dev@openjdk.org> Subject: JavaFX object traits There's a proposal to add a common interface that identifies JavaFX objects that can hold an Observable<Object, Object> property map: https://github.com/openjdk/jfx/pull/1215 The reason for this is obvious: allow JavaFX objects that can hold properties to be consumed by code without depending on brittle `instanceof` checks. The problem is real, but I think we can do much better than that. Why have a common interface at all? Well, of course it allows consumers to treat different objects in a uniform way. But there's more to it: the interface specifies the _meaning_ of the method; it guarantees that `Foo::getProperties` and `Bar::getProperties` are, in fact, not only methods with the same name, but the same semantics. `getProperties` and `hasProperties` is one example of such commonality between dissimilar classes like `Node` and `MenuItem`. But I've come across other examples in my own projects. For example, I'd like to consume JavaFX objects that have the `visible` and `disable` properties. Other applications will have different use cases, but since we don't know all possible use cases, it's hard to come up with a set of useful combinations of properties and methods. However, I think we can use the Java type system to allow applications to compose types that fit their unique use case. We begin by identifying common properties, and create trait interfaces that describe those properties: public final class javafx.scene.Trait { public interface Visible { BooleanProperty visibleProperty() default boolean isVisible()... default void setVisible(boolean value)... } public interface Disable { BooleanProperty disableProperty() default boolean isDisable()... default void setDisable(boolean value)... } public interface Properties { ObservableMap<Object, Object> getProperties() default boolean hasProperties()... } ... } These interfaces can now be implemented by all relevant JavaFX classes. This includes `Node`, `MenuItem`, and `Tab`, but applications are free to implement these trait interfaces themselves. Applications can now consume objects that implement any combination of traits, which gives applications the much-needed flexibility to use shared code for all kinds of JavaFX objects: <T extends Trait.Properties & Trait.Visible> void doSomething(T node) { node.getProperties().put("foo", "bar"); node.setVisible(true); } <T extends Trait.Text & Trait.Graphic> void doAnotherThing(T node) { node.setText("hello"); node.setGraphic(myGraphic); } What do you think?