次のコードがあるとしましょう:
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
関数に与える必要があります。あなた(およびメソッドを見ている人)にとっては明らかですが、ランタイム中にジェネリック型が消去されることはそれほど明白ではないかもしれません(ただし、ここでは主に推測です)。渡す果物があなたが期待しているジュースのサブタイプと実際に一致していないことを気にしない場合、次のことがあなたにとって何かかもしれません:
ただし、
AppleJuice
を確実にしたい場合Apple
でのみ構築できます s、次のような解決策しか考えられません。makeJuice
を追加するFruit
へ クラス、例えばmakeJuice
を追加する (/makeFrom
?)Juice
へ クラス、例えば他の中間オブジェクトを追加して、一度に2つのジェネリック型を必要としないようにします。
そしてそれを呼び出す
拡張機能を使用した上記のバリアント
ただし、すべてのタイプに対して指定する必要があります。以下は残念ながら機能しません。
その後、同じ問題が再び発生するため...
<Apple, AppleJuice>
を指定する必要があります 。しかし、おそらくこれらのどれもあなたが望んでいたものではありません。 そのため、すべてを処理する単一のメソッドが必要な場合は、(ラッパーを使用していても)おそらく3番目のバリアントが最適です。