3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Guava の EventBus で多相の値を扱うために試行錯誤した話

Last updated at Posted at 2013-08-07

百聞は一見に如かず。まずはこんなクラスを用意します。

public static class SampleHoge{
}
public class ValueEvent<T>{
	final private T x;

	public ValueEvent(T x) {
		this.x = x;
	}
	public T get(){
		return x;
	}
}
public static class HogeListener {
	@Subscribe
	public void show(ValueEvent<SampleHoge> x){
		Log.d("sample", "value:hoge:" + x.get());
	}
}

任意の型が含まれるイベントのうち、リスナが指定した型 ( ここでは SampleHoge ) のイベントのみが渡ってくるという動作を期待しています。さっそく使ってみましょう。

EventBus eventBus = new EventBus();
eventBus.register(new HogeListener());

eventBus.post(new ValueEvent<String>("hello, string!"));
eventBus.post(new ValueEvent<Integer>(1234));
eventBus.post(new ValueEvent<SampleHoge>(new SampleHoge()));
eventBus.post(new SampleHoge());

// value:hoge:hello, string!
// value:hoge:1234
// value:hoge:SampleHoge@406e3180// 本当はここだけ実行されてほしい

残念ながら期待どおりにはいきません。
でもこれは予想できていたことです。メソッド void show(ValueEvent<SampleHoge> x) の型パラメータ SampleHoge が type erasure で消されるのでしょう?そんなことは知ってますよ。フフン。

参考 : [What about a generic Handler interface?]
(https://code.google.com/p/guava-libraries/wiki/EventBusExplained#What_about_a_generic_Handler_interface?)

引数から型パラメータを消してみる

それならばと下記のようなクラスも試してみました。

public static class TypeBinder<T>{
	public class ValueEvent{
		final private T x;
		
		public ValueEvent(T x) {
			this.x = x;
		}
		public T get(){
			return x;
		}
	}
}
public static class HogeTypedListener extends TypeBinder<SampleHoge>{
	@Subscribe
	public void show(ValueEvent x){
		Log.d("sample", "typed-value:hoge:" + x.get());
	}
}

今回はメソッド void show(ValueEvent x) に型パラメータが現れていません。enclosing class (TypeBinder<T>) に与えられた型パラメータ T を inner class (ValueEvent) から参照している形です。

実行してみます。

EventBus eventBus = new EventBus();
eventBus.register(new HogeTypedListener());

eventBus.post((new TypeBinder<String>()).new ValueEvent("hello, string!"));
eventBus.post((new TypeBinder<Integer>()).new ValueEvent(1234));
eventBus.post((new TypeBinder<SampleHoge>()).new ValueEvent(new SampleHoge()));
eventBus.post(new SampleHoge());

// typed-value:hoge:hello, string!
// typed-value:hoge:1234
// typed-value:hoge:SampleHoge@406cef88// 本当はここだけ実行されてほしい

残念ながら結果はまるで変わりません。
でもこれも考えてみれば当たり前ですね。型パラメータの位置が変わっただけですから。

いずれの形でも ValueEvent 以外の場合に実行されていないことは確認できたので、イベントの型が一種類に保証されている場合は問題ないとも言えますが、しかしそれは何の解決にもなっていません。

悲しい

どうにかして EventBus で多相の値を扱うための回避策が欲しいところですが思いつきませんでした。誰か教えてください。

以上

失敗の記録が誰かのお役に立ちますように。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?