メソッドの返り値に共通のスーパークラスの型を付けたい
次のコードはコンパイルできて、実行すると"F"と表示します。
open class MyBool
class MyTrue : MyBool()
class MyFalse : MyBool()
fun <T> select(b: Boolean, v: T, w: T): T = if (b) v else w
fun main(args: Array<String>) {
val v: MyBool = select(false, MyTrue(), MyFalse())
when (v) {
is MyTrue -> println("T")
is MyFalse -> println("F")
}
}
このうちのselect
と同ようなメソッドでv
の代わりにthis.v
を返すものを定義したいのですが書き方が分かりません。例えば次のように書いた時、
class A<T>(val v: T) {
fun select(b: Boolean, w: T): T = if (b) v else w
}
A(MyTrue()).select(MyFalse())
をMyBool
として扱って欲しいのですが、実際は型エラーとなります。
Typing.kt:15:46: error: type mismatch: inferred type is MyFalse but MyTrue was expected
val v: MyBool = A(MyTrue()).select(false,MyFalse())
^
一応T
にout
修飾子を付加し、メソッドの代わりにextension functionを使えば近いことは達成できます。
class A<out T>(val v: T)
fun <T> A<T>.select2(b: Boolean, w: T): T = if (b) v else w
fun main(args: Array<String>) {
val v = A(MyTrue()).select2(false,MyFalse())
when (v) {
is MyTrue -> println("T")
is MyFalse -> println("F")
}
}
// コンパイル可、"F"を印字
select
関数と同じことをメソッドで実現するにはどうすればよいでしょうか?それともこのような場合はextension functionを使うのが筋なのでしょうか?