Cysharp / R3

The new future of dotnet/reactive and UniRx.
MIT License
1.71k stars 70 forks source link

Is there a technical reason as to why there are no interfaces for `Observable<T>`? #204

Open grofit opened 1 month ago

grofit commented 1 month ago

Long time user of rx and unirx and I am evaluating R3 but one thing that struck me right away was that there was no interfaces on most classes.

I was wondering if this was maybe because:

I am not massively fussed but a use case that came up when evaluating was I had some code which had the notion of an IComputed<T> which inherited from IObservable<T> and there was a few interfaces that built on top of that IComputed but ultimately it provided IReadOnlyReactiveProperty like functionality but with the user specifying how the computed should be hooked up.

Anyway none of that is really important, but I can no longer have my IComputed depending on an underlying interface which again isnt a massive problem but it got me wondering why there was no interface provided and if maybe there is some merit to having one.

ninjaoxygen commented 1 month ago

Long time user of Rx coming to R3 for the first-class async/await support and performance.

I think I have similar struggles with the lack of interfaces.

As an example, I have objects that were implemented as a subclass of a ReactiveProperty (our api exposes a single Observable that can be subscribed to different underlying observables, the underlying data comes from Orleans observers), so I then want to expose IDisposable and Observable without exposing OnNext on the ReactiveProperty used by implementation. Cannot use inheritance to hide OnNext as it is not virtual.

Without interfaces, it ends up being two objects, a proxy facade for the Observable and the property implementation as a field. With interfaces, this could be a single object.

ninjaoxygen commented 1 month ago

@grofit thanks for mentioning ReadOnlyReactiveProperty / .ToReadOnlyReactiveProperty() that solves the problem I had above.

Can IComputed<T> possibly be built to expose only ReadOnlyReactiveProperty<T> objects, but with a more-derived class as the implementation?

I am headed down a similar path where an Observable<string> can be used as the key to a Dictionary<string, Observable<T>> to switch between observables. I was doing this in code for each usage, but building a computed expression syntax would be a lot nicer in the long term.

grofit commented 1 month ago

Glad you solved your problem, for me its not really a problem I have as such, just as there are very few interfaces it just means my interfaces are now the start of a chain which feels wrong as I want them to adhere to the same sort of contract as the R3 types but without being tied to an inheritance chain.