メソッドの返り値に共通のスーパークラスの型を付けたい


次のコードはコンパイルできて、実行すると"F"と表示します。

[code]

    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")
        }
    }
    
[/code]

このうちの`select`と同ようなメソッドで`v`の代わりに`this.v`を返すものを定義したいのですが書き方が分かりません。例えば次のように書いた時、

[code]

    class A<T>(val v: T) {
       fun select(b: Boolean, w: T): T = if (b) v else w
    }
    
[/code]

`A(MyTrue()).select(MyFalse())`を`MyBool`として扱って欲しいのですが、実際は型エラーとなります。

[code]

    Typing.kt:15:46: error: type mismatch: inferred type is MyFalse but MyTrue was expected
        val v: MyBool = A(MyTrue()).select(false,MyFalse())
                                                 ^
    
[/code]

一応`T`に`out`修飾子を付加し、メソッドの代わりにextension functionを使えば近いことは達成できます。

[code]

    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"を印字
    
[/code]

`select`関数と同じことをメソッドで実現するにはどうすればよいでしょうか？それともこのような場合はextension
functionを使うのが筋なのでしょうか？




このサンプルのように

[code]

    val v: MyBool = A(MyTrue()).select(false,MyFalse())
    
[/code]

としてしまうと型推論によって class A は `A<MyTrue>` となってしまうと思います。そこで、

[code]

    val v: MyBool = A<MyBool>(MyTrue()).select(false,MyFalse())
    
[/code]

とすることで想定通りの動作をするかと思います。

動作を確認したものがこちら。
<https://try.kotlinlang.org/#/UserProjects/2hdaktdk2ubim65qmc67156679/658bm9nn5ih7q59m26vt04c4gt>




このサンプルのように

[code]

    val v: MyBool = A(MyTrue()).select(false,MyFalse())
    
[/code]

としてしまうと型推論によって class A は `A<MyTrue>` となってしまうと思います。そこで、

[code]

    val v: MyBool = A<MyBool>(MyTrue()).select(false,MyFalse())
    
[/code]

とすることで想定通りの動作をするかと思います。

動作を確認したものがこちら。
<https://try.kotlinlang.org/#/UserProjects/2hdaktdk2ubim65qmc67156679/658bm9nn5ih7q59m26vt04c4gt>

