仅将标记为具体化的类型传递给Kotlin泛型函数

仅将标记为具体化的类型传递给Kotlin泛型函数,kotlin,kotlin-generics,kotlin-reified-type-parameters,Kotlin,Kotlin Generics,Kotlin Reified Type Parameters,假设我有以下代码: 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 {} 但我不想传递类对象,而是想将appleguice作为

假设我有以下代码:

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 {}
但我不想传递类对象,而是想将
appleguice
作为类型传递:

val appleJuice : AppleJuice = makeJuice<AppleJuice>(Apple())
但现在我必须指定两种类型:

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

理论上,
Apple
type不应该是必需的,因为它已经从
appleguice
type中知道了。有没有可能不传递不必要的类型,而只传递那些被具体化的类型?

我看到您的解决方案的主要问题是,您在
makeJuice
-方法上要求两个泛型类型。
F
J
都需要赋予该函数。虽然这对您(以及任何查看该方法的人)来说都是显而易见的,但我认为在运行时删除泛型类型时,这可能不是那么明显(但现在这主要是一个猜测)

如果您不介意您正在传递的水果与您期望的果汁的子类型不匹配,那么以下内容可能适合您:

inline fun <reified J : Juice<out Fruit>> makeJuice(fruit : Fruit) : J = TODO()
  • makeJuice
    (/
    makeFrom
    ?)添加到
    Juice
    类,例如

    open class Juice<T : Fruit> {
      fun makeFrom(fruit : T) { TODO() }
    }
    
    开放类果汁{
    乐趣来自(水果: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)
    
    class果汁机(val水果:F){
    inline fun makeJuice():J=TODO()
    }
    使用乐趣(水果:F)=果汁机(水果)
    
    并称之为

    using(Apple()).makeJuice<AppleJuice>()
    
    使用(Apple()).makeJuice()
    
  • 使用扩展功能的上述变体,例如

    inline fun <reified J : Juice<out Apple>> Apple.makeJuice() : J = TODO()
    
    inline fun Apple.makeJuice():J=TODO()
    
    但您需要为所有类型指定它。不幸的是,以下措施行不通:

    inline fun <F : Fruit, reified J : Juice<F>> F.makeJuice() : J = TODO()
    
    inline fun F.makeJuice():J=TODO()
    
    我们又遇到了同样的问题。。。并且需要指定

  • 但也许这些都不是你希望得到的。
    因此,如果您想用一个方法来处理所有问题,那么第三个变体可能是您的最佳选择(即使它使用了包装器)。

    在这种情况下,是否可以将
    makeJuice
    函数放在
    Juice
    类中?如果您实际传入的
    水果不重要,然后您可以删除
    F
    并使用
    Juice
    Fruit
    参数来代替。@Mosius不,这是不可能的。它必须是静态方法扩展函数也是静态方法。。。扩展函数可以吗?;-)好。。。我不认为你可以有一个单一的静态函数和你想要的具体类型(也就是说,你实际上需要2个泛型类型)。我的答案中的变体3可能是您在不编写大量附加实现的情况下所能获得的最好版本。
    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()