TomasMikula / ReactFX

Reactive event streams, observable values and more for JavaFX.
BSD 2-Clause "Simplified" License
376 stars 47 forks source link

Should Val<T> interface extends ObservableObjectValue<T>? #17

Open cardamo opened 9 years ago

cardamo commented 9 years ago

Like in the MonadicObservableValue<T> from EasyBind extending ObservableObjectValue makes Val compatible with some methods of javafx.beans.binding.Bindings.

TomasMikula commented 9 years ago

For purely pragmatic reasons to be more compatible with JavaFX interfaces, it probably should extend ObservableObjectValue. I never liked the fact that there is the type ObservableObjectValue, which itself does not add anything to the ObservableValue interface. Even worse, some methods in Bindings, as you say, require ObservableObjectValue where they could just as well accept ObservableValue.

I thought that you can at least convert ObservableValue<T> into ObservableObjectValue<T>, like you can convert ObservableValue<Boolean> into ObservableBooleanValue using BooleanExpression.booleanExpression(ObservableValue<Boolean>), but no, ObjectExpression.objectExpression() only accepts ObservableObjectValue. Sigh.

I am not sure whether I should resign and extend ObservableObjectValue, or provide helper methods equivalent to those in javafx.beans.binding.Bindings that accept ObservableValue.

Anyway, do you have any specific methods from Bindings in mind? Most of them can be replaced by map(f) or Val.combine(...), which are more general.

Part of why I am somewhat reluctant to extend ObservableObjectValue is that the name suggests that the values are objects. While this is always the case for now (generic type parameters must be Objects, not primitives), it will not be the case in the future, when project Valhalla is implemented (probably JDK 10). It will allow generics over primitive types as well.

ObservableValue can then be redeclared as

interface ObservableValue<any T> { // this may not be the actual syntax in the end
}

I doubt that ObservableObjectValue<T> would be redeclared to ObservableObjectValue<any T>, since, as its name indicates, it is supposed to be used for Objects.

Project Valhalla will also add conditional methods, that is methods that are available only when the actual type argument is of certain type. For example, we could define a method ObservableValue<T>.and(ObservableValue<Boolean>) that is accessible only when T is in fact Boolean (or boolean). This will make all the specialized interfaces like ObservableDoubleValue, ... obsolete.

All the DoubleExpression, ... interfaces are already obsolete now, since their methods could (and should) be moved to ObservableDoubleValue, ... interfaces as default methods.

Val makes the interface Binding obsolete, because there is no need to dispose() a Val (just remove listeners).

So I foresee a future where something like Val<T> and Var<T> is all you need.