ニートが学ぶUniRx 入門編その1

はいどーもこんにちはキングオブニートです。
イケてるUnityエンジニアの使用率が90%を超えている(適当なので真に受けないで)UniRxについて本日は学んでいきたいと思います。
ちなみに以下のサイトをもとに進めていきます。
https://qiita.com/toRisouP/items/2f1643e344c741dd94f8

注*学習中なので内容が正確かどうかは一切保証しません。ただの備忘録です。ご了承ください。

UniRxとは

とりすーぷさんによれば「UniRxはeventの完全上位互換」らしいです。
これを別の視点から見れば、eventを理解できていなければUniRxの何がよいのかを理解することは困難ということでしょう。
幸い僕はeventくらいならわかるので、前提条件は満たしていますね。

とりあえず使ってみる

つかみとして、とりすーぷさんのTimeCounterクラスのサンプルをそのまま真似してみました。
クラスの関係でわかったことは以下の通りです。

・SubjectクラスはISubjectインターフェイスを実装している
・ISubjectインターフェイスはIObservableインターフェイスを継承しています。
・したがってIObservable型のプロパティのゲッターとしてSubject型のインスタンスを使用することができる

各メソッドの使い方でわかったことは以下の通りです。

・SubjectクラスのOnNextメソッドはイベントの発火を意味する?
・OnNextメソッドの引数に値を渡しておくと、イベント発火時に全ての購読側に値が伝わる
・購読側のクラスではSubscribeメソッドでイベントハンドラを登録する(イベントで言う+=みたいなもん)

とりあえず今はこんな感じでしょうか。

OnNextとSubscribe

こちらもとりすーぷさんのサンプルを読みつつ進めていきます(以降は特に何も書きませんが、基本的にとりすーぷさんの記事を参照していると思ってください)。

説明とサンプルコードによれば、Subscribeで登録する関数はいくつでもよいようです。
まあ一つだけに限定だとあまりにも不便(というか使う意味がない?)なのでこれは直感的ですね。
OnNextメソッドでイベントを発火(Subscribeで登録した関数にイベントが起きたことを伝える)とき、登録した関数一つ一つにメッセージを渡しつつ処理がおこなわれるようです。
これもC#のイベントを理解していればごく直感的に理解できる動作ですね。
たぶんですけど、登録順に実行されるんですかね?
確認していませんが……。

IObserverとIObservable

とりすーぷさんの記事によれば「SubjectはIObserverインターフェースとIObservableインターフェースの2つを実装している」とのことです。
実際、UniRxのコードを眺めてみるとそのようになっています。
具体的には

・SubjectクラスはISubjectインターフェイスを実装している
・ISubjectインターフェイスはISubjectとIObserverとIObservableを継承している

となります。

IObserverインターフェイスとは何なのか?

IObserverとは、ズバリこちらです。
しかしインターフェイスだけを見てもさっぱり何もわからんわけでして(名前からある程度の予測はできますが)、さりとて具象クラスを読み込めるほどUniRxに精通していない僕なんかは、他の人が書いてくれた解説を読むのが一番早いです。
知ったことをまとめると以下のような感じでしょうか。

・IObserverインターフェイスはイベントを発行する側のためのインターフェイス
・OnNextは先に見た通り
・OnErrorは何かしらの例外を投げなければならないときに使う?
・OnCompletedはSubjectの動作を停止させるときに発行する?

ですかね。
まだ実際にコードを書いていないのでOnCompletedとOnErrorの使い方に謎が残りますが、気にせず進んでいきます。

IObservableインターフェイスとは何なのか?

IObservableとはズバリこちらです。
Subscribeメソッドがありますね。
今のところはイベントを登録するメソッドだと思っておけば当たらずといえども遠からずでしょうか(+=演算子的な)。

さてこのインターフェイスに定義されているSubscribeメソッドですが、いくつかのオーバーロードがあります。
OnNextに対して関数を登録するだけでなく、OnCompletedやOnErrorに関数を登録するバージョンもある、ということですね。
これはイベントと違うところであり、言い換えればイベントの上位互換と言える機能でしょう。
実際にはOnNextだけを使う場合がほとんどらしいのですが、覚えておいて損はないなと思いました。

つまりSubjectってなんだってばよ

以上をまとめると、Subjectは「イベントを受け取る機能」と「イベントを発火する機能」の二つを持っていると言えそうです。
二つの側面を持っているため結構ややこしいですが、C#のイベント機能を念頭に置きながら理解するとよい感じなんじゃないかなあと思いました。

オペレータってなんぞ

UniRxでは「大本のSubjectと末端のSubscribeの間に挟み込んでいろいろメッセージを処理する部品」のことをオペレータと呼ぶらしいです。
実装や思想はともかく「メソッドチェーンで何やらできるLINQっぽいナンカ」と言う理解が直感的ですかね。
もちろんLINQには存在しないオペレータもありますが、共通する名前のオペレータもあるのでそれらは理解しやすいです。
ちなみにこのオペレータですが、IObserverとIObservableを実装するクラスを作れば自作も可能なようです(これもLINQと似てますね)。

ストリームってなんぞ

UniRxには「ストリーム」という用語が出てきます。
とりすーぷさんによればUniRxにおけるストリームとは「メッセージが発行されてからSubscribeに到達するまでの一連の処理の流れ」を意味する言葉らしいです。
まとめると以下のような感じでしょうか。

・一番最初のSubjectがメッセージ発行する
・必要があればオペレータがメッセージを処理する(ストリームの構築)
・Subscribeに到達(ストリームの可動)

まだ判然としておらず理解が不十分ですが、Subjectからドンドン押し込まれていくイメージですかね。

終わりに

ごくごく簡単な使い方は理解できました。
今の時点ではイベントプラスアルファかなという印象ですね。
続きの記事も読んでみたいと思いますよ。

ほなそんな感じでまた。
あ、お仕事も募集中です。

フォローする