Well, the topic of this thread was "Ability to decorate ChangeListener“
So, any solution, provided by JavaFX core, would have been fine … I still think 
this would be nice, proposing the if flip was a fault for this discussion ... 
Unhappily :-(


Am 24.03.2014 um 16:19 schrieb Stephen F Northover 
<steve.x.northo...@oracle.com>:

> I'm pretty sure this discussion has solidified around not flipping the 
> equals() but this is a good example of something that we wouldn't change.  If 
> you write code that relies on this, it will break in the future when new code 
> is added in FX that does not follow the pattern.
> 
> Steve
> 
> On 2014-03-22 10:47 AM, Mario Ivankovits wrote:
>> The only thing which I ask for is to flip this „if" in the *ExpressionHelper 
>> classes:
>> So, JavaFX does not break anything and it is up to the app developer to take 
>> the risk or not.
>> 
>> 
>>                    if (listener.equals(changeListeners[index])) {
>> 
>> If we flip this to
>> 
>>                if (changeListeners[index].equals(listener))
>> 
>> 
>> 
>> Am 22.03.2014 um 15:42 schrieb Kevin Rushforth 
>> <kevin.rushfo...@oracle.com<mailto:kevin.rushfo...@oracle.com>>:
>> 
>> If you are talking about a change to the JavaFX API, we are not likely to 
>> accept such a change if it breaks the contract of equals() or hashcode(). In 
>> your own app it may not matter, but it is dangerous to assume it won't 
>> matter to anyone. Martin owns the core libraries and can comment further.
>> 
>> -- Kevin
>> 
>> 
>> Mario Ivankovits wrote:
>> 
>> Hi Thomas!
>> 
>> Thanks for your input. Because I want to decorated listeners added by JavaFX 
>> core I can not use the sub/unsub pattern.
>> Your second proposal is almost what I do right now. In removeListener I 
>> consult a map where the decorated listeners and their undecorated one lives.
>> 
>> Regarding the symmetric doubts. Such listeners will always be removed by 
>> passing in the undecorated object to removeListener.
>> They should act like a transparent proxy.
>> 
>> Even if this breaks the equals paradigm, in this special case I can 
>> perfectly live with an equals/hashCode implementation like this below.
>> It won’t break your app; as long as both objects do not live in the same 
>> HashSet/Map …. for sure - but why should they?
>> 
>>     @Override
>>     public boolean equals(Object obj)
>>     {
>>         return obj == delegate; // && this == obj
>>     }
>> 
>>     @Override
>>     public int hashCode()
>>     {
>>         return delegate.hashCode();
>>     }
>> 
>> 
>> Regards,
>> Mario
>> 
>> 
>> Am 22.03.2014 um 14:22 schrieb Tomas Mikula 
>> <tomas.mik...@gmail.com><mailto:tomas.mik...@gmail.com>:
>> 
>> 
>> 
>> A simpler and more universal solution is to also override removeListener:
>> 
>> public void removeListener(ChangeListener<? super T> listener) {
>>    super.removeListener(decorated(listener));
>> }
>> 
>> And the equals() method on decorated listeners only compares the
>> delegates (thus is symmetric).
>> 
>> Regards,
>> Tomas
>> 
>> 
>> On Sat, Mar 22, 2014 at 2:07 PM, Tomas Mikula 
>> <tomas.mik...@gmail.com><mailto:tomas.mik...@gmail.com> wrote:
>> 
>> 
>> The suspicious thing about your solution is that your smart
>> implementation of equals() is not symmetric.
>> 
>> In case the observable value is visible only within your project, you
>> could do this:
>> 
>>    interface Subscription {
>>        void unsubscribe();
>>    }
>> 
>>    class MyObservableValue<T> implements ObservableValue<T> {
>>        public Subscription subscribe(ChangeListener<? extends T> listener) {
>>            ChangeListener<T> decorated = decorate(listener);
>>           addListener(decorated);
>>           return () -> removeListener(decorated);
>>        }
>>    }
>> 
>> and use subscribe()/unsubscribe() instead of addListener()/removeListener():
>> 
>>    Subscription sub = observableValue.subscribe(listener);
>>    // ...
>>    sub.unsubscribe();
>> 
>> Of course this is not possible if you need to pass the observable
>> value to the outside world as ObservableValue.
>> 
>> Regards,
>> Tomas
>> 
>> On Sat, Mar 22, 2014 at 6:57 AM, Mario Ivankovits 
>> <ma...@datenwort.at><mailto:ma...@datenwort.at> wrote:
>> 
>> 
>> Hi!
>> 
>> In one of my ObservableValue implementations I do have the need to decorate 
>> ChangeListener added to it.
>> Today this is somewhat complicated to implement, as I have to keep a map of 
>> the original listener to the decorated one to being able to handle the 
>> removal process of a listener. Because the outside World did not know that I 
>> decorated the listener and the instance passed in to removeListener ist the 
>> undecorated one.
>> 
>> We can make things easier with a small change in 
>> ExpressionHelper.removeListener. When iterating through the listener list, 
>> the listener passed in as argument to removeListener is asked if it is equal 
>> to the one stored
>> 
>>                    if (listener.equals(changeListeners[index])) {
>> 
>> If we flip this to
>> 
>>                if (changeListeners[index].equals(listener)) {
>> 
>> a listener decoration can be smart enough to not only check against itself, 
>> but also against its delegate.
>> 
>> What do you think?
>> 
>> I could prepare a patch for the *ExpressionHelper classes.
>> 
>> 
>> Best regards,
>> Mario
>> 
>> 
>> 
>> 
>> 
>> 
>> 
> 

Reply via email to