trait A { type Self <: A }class B extends A { type Self = B }ってよくやるけどもっといい方法はあるのだろうか。
— ねこはるさん (@halcat0x15a) 2月 17, 2012
に対し、りりかるろじかるさんが反応をくれたので書いてみます。
最初に、これが何の役に立つかですが、
と定義したとき、
となります。
ポイントは、
- Barからfを呼び出すとBarが返る。
- Barからgを呼び出すとOption[Bar]が返る。
- fの返り値からhを呼び出せる。
つまり、スーパークラスでサブクラスの値を返すことができるということです。
しかし、これにはサブクラスがいちいちSelfを定義しなければいけないので楽したいですよね。
そこで、りりろじさんに考えて頂いた方法を書いていきます。
this.type
this.typeを使って定義すると、
となります。
Bar.this.typeが要求されているところでBarを渡すとコンパイルエラーがでます。
なので、asInstanceOfを使って定義します。
なんかエラー出てる・・・・
うーん、これはどういうことでしょう?
gの返り値をOption[this.type]と明示的に書いても変わりません。
むむむむむ・・・・・えらいひと、教えて下さい。
型パラメータ
Genericsまんせー
ということで書いてみる。
おお、ちゃんと動きますね。
この型パラメータ版とtype Self版で比べてみると、
- 型パラメータ有無
- どちらも、型の情報がなくなると意味がない
- 継承元がtype Selfを書くか、型パラメータに型を書くか
型パラメータを使ったほうが楽に書けそうですが、type Selfを使うと楽になることもあります。
このように、複数のtraitでSelfを使う場合はこの書き方が有利なようです。
他にもっといい方法があったら是非教えてくださいねー!
0 件のコメント:
コメントを投稿