ニートが学ぶUniRx UniRxの成り立ち

はいどーも以下略。
本日はこの記事をもとに進めて行きたいと思いますよ。
https://qiita.com/mattak/items/106dfd0974653aa06fbc

途中までは

項目3あたりまでは普通のObserverパターン+αと言う感じですね。
DisposableもIDisposableを使ったことがあれば「フムフム」という感じです。
強いて言うと内部クラスを久しぶりに見た(もとい僕は使ったことがないw)ので、ちょっと引っかかったくらいでしょうか。

Observable

ここです。
ここがまさに僕がよくわからなかった場所です。

・ObserverをSubscribeする
・SubjectがOnNextを呼ぶ

ここまでは問題なく理解できました。
ですがUniRxのSubjectはIObserverとIObservableを実装しているのです。
これはつまり、監視者であると同時に監視可能であるということでもあります。
意味が全くわからず悩みに悩んでいたのですが、この解説記事は悩みを少しほぐしてくれました。
ひとまず説明をそのまま引用します。

NotifyNext(next) はすぐに OnNext(value) を呼び出します。
監視対象の ISubjectはイベントの実行タイミングで考えると、IObserverと同等です。
つまり Subjectは 監視者(IObserver) であり監視対象 (IObservable) であるとみなせます.

今までNotifyNext(value)などとしていた部分については「Subjectは監視者である」という性質と「NotifyNext(value)とOnNext(value)の実行タイミングが同等である」という性質を利用し、一つにまとめています。
また、Subjectは監視可能でもあるため、IObservableも継承し、Subscribeの実装を強制します。

さらにこの項目の最後に、以下の一文がありました。
「Subjectのようにすぐに来たイベントを流してしまうような IObservableのことを Hotであると呼称します.」
さらりと書かれていますが、これは非常に重要な気がしています。
「来たイベントをすぐ流す」とは、すなわちすぐ通知するということですかね。
もうちょっと読み進めて行きたいです。

Cold Observable

これはちょっとややこしいですね。
まずは静的なクラスを別物として抽出してみます。

Create静的メソッドは引数に(多くの場合は)ラムダ式を受け取ります。
そして受け取ったラムダ式をもとに、新たなObservable型のインスタンスを生成しています。
Observable型のクラスがObservable型のクラスを生成しているところがポイントでしょうか。

他の部分も見てみます。
コンストラクタでCreateメソッドと全く同じ引数を受け取ることになっています。
それをフィールドcreatorに保存していますね。
そしてSubscribeが実行されたとき、creator関数を即時実行しています。
戻り値は単なる解放用のものですね。

実例も見てみましょう。
最初にObservableクラスの静的メソッドであるCreateメソッドを利用して、Observable型のインスタンスを生成しています。
普通にnewで作っても一応問題ないはずですが、ここではCreateメソッドを使用していますね。

生成されたインスタンスはまだ何もおこないません。
サンプルでは次にSushiObserverクラスのインスタンスを生成しています。
このクラスはIObserverを実装しているので、OnNextやらOnCompleteやらを実装していることになりますね。

最後に、最初に作成したObservable型のインスタンスのSubscribeメソッドを実行しています。
引数には先程のobserverを渡していますね。
Subsribeした瞬間に関数を実行するようになっているため、observableのインスタンスを作成するときに書いたラムダ式が実行されます。
このとき、ラムダ式にobserverが渡されます。

この辺から実装部分がかなりややこしいです。
正直ついていくのがやっとです。

ちなみに、処理が即時実行されず、Subscribeするまで処理が遅延されることをColdであると言うようです。
Hotと一緒に覚えておきたいですね。

Operator: Where

今度はオペレータの話ですね。
独立して読みやすいIObservableExtensionをまず見てみます。
WhereがIObservableの拡張メソッドとして定義されていますね。
いわゆる条件を受け取って、その結果をWhereObservable型のインスタンスとして返しています。
WhereObservable型はIObservable型を実装しているため、メソッドチェーンとして機能させることもできるようです。

では肝心のWhereObservableはどうでしょうか。
コンストラクタでIObservable型と、条件式を表す関数を受け取っています。
SubscribeされたときにIDisposable型の新しいインスタンスを生成しています。
きっとこれが何やらしてメソッドチェーンを形成したときにきちんと動くようになるのでしょうが、正直よくわかりませんでした……。
OnNextが伝達する経路とかどうなってるんですかねこれ。

if (this.operation(next)) observer.OnNext(next);
この部分で条件式に当てはまらないのを弾いてるのはわかるのですが、その後にOnNextで次のオペレータに進めているんですかね……。
SubjectがOnNextを呼んだときの挙動が全然わかりません。

もう完全についていけてません。

Select

これもWhereが理解できていないので、同じく理解できません。
しかしSelectそのものの理屈としてはかなりシンプルで、コンストラクタで受け取ったoperationを利用して変換してるだけなんですね。
うーん、どうやって次のオペレータに進んでるんでしょう……。

SelectManay

なんかすごいらしいですよ。
アハハハハ。

Unityでの利用

購読するときにボタンにイベントハンドラーとしてObserverのOnNextを呼ぶ処理を登録していますね。
だからOnNext呼んだらなんでそれがこうであーなんねん。

終わりに

途中まで「なるほど?」という感じだったのですが、最終的に全然わからないということがわかりました。
本当にありがとうございました。

ほなそんな感じでまた。

フォローする