我正在原型化一些高度声明性的代码, Kotlin 提供的类型推断和类型安全帮助了很多。其中一个目标是使主要类型的扩展(子类)容易实现。为了保持丰富的类型推断和表达性,我发现通过针对子类定义泛型扩展函数可以取得一定的成功。所有子类方法的类型信息都没有额外的子类实现,这太棒了。
因此,我试图编写一个保留尽可能多类型信息的丰富泛型函数。问题在于这个函数操作潜在递归的泛型类型,并且我想重新排列泛型类型参数。
如果没有示例,这将是不可能描述的。所以考虑以下内容:
我们希望有一个通用的函数能够有效地实现这个功能。
有没有不行的理由?例如,将它作为语言功能添加进去?我很同情物流原因反对的观点,但我很好奇在原则上是否可能。
最后注意事项: - 这让我想起了类型别名,除了通用类型参数本身。实际上,我在示例中包含了该关键字,以帮助消化。不过,这不是唯一部分,请注意语法中的 和 。 - 它几乎让我想起单子,只不过是针对类定义本身,如果这在一种手势摇摆、直观的方式下有意义的话。 - 我还不知道如何实现主体,但我还没有那么远,因为我仍然在尝试看看签名是否可能:p
因此,我试图编写一个保留尽可能多类型信息的丰富泛型函数。问题在于这个函数操作潜在递归的泛型类型,并且我想重新排列泛型类型参数。
如果没有示例,这将是不可能描述的。所以考虑以下内容:
open class G<in T>
class A<in T> : G<T>()
class B<in T> : G<T>()
class C<in T> : G<T>()
val ba = B<A<*>>()
val cb = C<B<*>>()
我们希望有一个通用的函数能够有效地实现这个功能。
fun B<A<*>>.doTransitiveThing(c: C<B<*>>) : C<A<*>>
{
// implement
}
val ca = ba.doTransitiveThing(cb) // Returns C<A<*>>
目标标准:
- 以
C
为参数并返回C
,但泛型类型参数不同 - 我想将此行为概括为
G
的所有子类的扩展函数- 它必须是扩展函数,这样使用泛型类型时我们可以拥有子类的类型,并确保参数具有接收器类型的泛型类型参数。
- 换句话说,我们希望为
G
的子类编写一个扩展函数,因此在调用时,参数必须是C<B<*>>
而不是C<G<*>>
这描述了问题的要点。我不确定语言是否支持我想要的,也不确定类型擦除是否是不可能实现的因素,但迄今为止我找不到这个因素(如果是这样,也许我需要帮助)。
以下内容接近题意:
fun <
TargetGenericType,
Arg1Type: G<*>,
ReceiverType: G<TargetGenericType>,
Arg2Type: G<Arg1Type>,
ResultType: G<TargetGenericType>
>
ReceiverType.doTransitiveThingGeneric(x: Arg2Type): ResultType
{
//implement
}
val ca2 = ba.doTransitiveThingGeneric(cb)
但是还有一些问题
- 它返回
G<A<*>>
而不是C<A<*>>
。如果它能返回C
并且不丢失类型信息的话,那就太好了(否则我其实也没用这个函数) - 技术上讲,
ReceiverType
不一定是Arg1Type
往前想,如果以下类似的代码在Kotlin中是有效的,我认为它可以解决我的问题
fun <
TargetGenericType,
ReceiverBaseType<T>: G<T>,
typealias ReceiverType = ReceiverBaseType<TargetGenericType>,
ParamBaseType<U>: G<U>,
typealias ParamType = ParamBaseType<ReceiverBaseType<*>>,
ResultType: ParamBaseType<TargetGenericType>
>
ReceiverType.doTransitiveThingHigherOrderGeneric(x: ParamType): ResultType
{
//implement
}
有没有不行的理由?例如,将它作为语言功能添加进去?我很同情物流原因反对的观点,但我很好奇在原则上是否可能。
最后注意事项: - 这让我想起了类型别名,除了通用类型参数本身。实际上,我在示例中包含了该关键字,以帮助消化。不过,这不是唯一部分,请注意语法中的 和 。 - 它几乎让我想起单子,只不过是针对类定义本身,如果这在一种手势摇摆、直观的方式下有意义的话。 - 我还不知道如何实现主体,但我还没有那么远,因为我仍然在尝试看看签名是否可能:p
inline fun <reified T> B<A<T>>.doTransitiveThing(c: C<B<T>>) : C<A<T>>
? - Just another metaprogrammer