ホーム>source

次のコードがあるとしましょう:

open class Fruit
class Apple : Fruit()
open class Juice<T : Fruit>
class AppleJuice : Juice<Apple>()
fun <F : Fruit, J : Juice<F>> makeJuice(juiceClass : Class<J>, fruit : F) : J {}

このような関数を呼び出します:

val appleJuice : AppleJuice = makeJuice(AppleJuice::class.java, Apple())

しかし、クラスオブジェクトを渡す代わりに、 AppleJuice を渡したい  タイプとして:

val appleJuice : AppleJuice = makeJuice<AppleJuice>(Apple())

関数をリファクタリングして reified にインライン化しました :

inline fun <F : Fruit, reified J : Juice<F>> makeJuice(fruit : F) : J {}

しかし、今は両方のタイプを指定する必要があります。

val appleJuice : AppleJuice = makeJuice<Apple, AppleJuice>(Apple())

理論的には、 Apple  タイプは AppleJuice からすでにわかっているため、タイプは必要ありません  タイプ。不要な型を渡すことを取り除き、 reified として作成された型のみを渡すことはどういうわけか可能です ?

あなたの答え
  • 解決した方法 # 1

    あなたのソリューションで私が見る主な問題は、あなたがあなたの makeJuice で2つのジェネリックタイプを求めているということです -方法。両方 F  および J  関数に与える必要があります。あなた(およびメソッドを見ている人)にとっては明らかですが、ランタイム中にジェネリック型が消去されることはそれほど明白ではないかもしれません(ただし、ここでは主に推測です)。

    渡す果物があなたが期待しているジュースのサブタイプと実際に一致していないことを気にしない場合、次のことがあなたにとって何かかもしれません:

    inline fun <reified J : Juice<out Fruit>> makeJuice(fruit : Fruit) : J = TODO()
    
    

    ただし、 AppleJuice を確実にしたい場合   Apple でのみ構築できます s、次のような解決策しか考えられません。

    makeJuice を追加する   Fruit へ  クラス、例えば

    abstract class Fruit {
      abstract fun makeJuice() : Juice<out Fruit>
    }
    // and subclasses:
    class Apple : Fruit() {
      override fun makeJuice(): AppleJuice = TODO()
    }
    
    

    makeJuice を追加する  (/ makeFrom ?) Juice へ  クラス、例えば

    open class Juice<T : Fruit> {
      fun makeFrom(fruit : T) { TODO() }
    }
    
    

    他の中間オブジェクトを追加して、一度に2つのジェネリック型を必要としないようにします。

    class JuiceMaker<F : Fruit>(val fruit : F) {
      inline fun <reified J : Juice<F>> makeJuice() : J = TODO()
    }
    fun <F : Fruit> using(fruit : F) = JuiceMaker(fruit)
    
    

    そしてそれを呼び出す

    using(Apple()).makeJuice<AppleJuice>()
    
    

    拡張機能を使用した上記のバリアント

    inline fun <reified J : Juice<out Apple>> Apple.makeJuice() : J = TODO()
    
    

    ただし、すべてのタイプに対して指定する必要があります。以下は残念ながら機能しません。

    inline fun <F : Fruit, reified J : Juice<F>> F.makeJuice() : J = TODO()
    
    

    その後、同じ問題が再び発生するため... <Apple, AppleJuice> を指定する必要があります 。

    しかし、おそらくこれらのどれもあなたが望んでいたものではありません。 そのため、すべてを処理する単一のメソッドが必要な場合は、(ラッパーを使用していても)おそらく3番目のバリアントが最適です。

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ javascript - 形:パラメーター名なしで選択した値を渡す