ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java-Kotlin:泛型和方差

2019-10-25 21:05:00  阅读:264  来源: 互联网

标签:kotlin generics covariance java


我想在Throwable上创建一个扩展函数,给定一个KClass,它以递归方式搜索与该参数匹配的根本原因.以下是一种可行的尝试:

fun <T : Throwable> Throwable.getCauseIfAssignableFrom(e: KClass<T>): Throwable? = when {
    this::class.java.isAssignableFrom(e.java) -> this
    nonNull(this.cause) -> this.cause?.getCauseIfAssignableFrom(e)
    else -> null
}

这也适用:

fun Throwable.getCauseIfAssignableFrom(e: KClass<out Throwable>): Throwable? = when {
    this::class.java.isAssignableFrom(e.java) -> this
    nonNull(this.cause) -> this.cause?.getCauseIfAssignableFrom(e)
    else -> null
}

我这样调用该函数:e.getCauseIfAssignableFrom(NoRemoteRepositoryException :: class).

但是,关于泛型的Kotlin docs说:

This is called declaration-site variance: we can annotate the type
parameter T of Source to make sure that it is only returned (produced)
from members of Source, and never consumed. To do this we provide
the out modifier

abstract class Source<out T> {
    abstract fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // This is OK, since T is an out-parameter
    // ...
}

在我的情况下,参数e不返回而是被消耗.在我看来,应该将其声明为e:KClass< in Throwable>.但这不能编译.但是,如果我把out看作是“您只能从中读取或返回它”,而将in看作是“您只能为其写入或分配一个值”,那么这是有道理的.有人可以解释吗?

解决方法:

在您的情况下,您实际上并没有使用type参数的方差:您永远不会传递值或使用从对e:KClass< T>的调用返回的值.

方差描述了您可以使用哪些值作为参数,以及在使用投影类型时(例如在函数实现内部)从属性和函数返回的值中可以期望得到什么.例如,其中KClass< T>将返回T(如签名中所写),KClass< out SomeType>.可以返回SomeType或其任何子类型.相反,当KClass< T>会期望参数T为SomeType中的KClass<期望SomeType的某些超类型(但确切地未知). 实际上,这定义了传递给此类函数的实例的实际类型参数的限制.对于不变类型KClass< Base&gt ;,您不能传递KClass< Super>或KClass< Derived> (其中派生:基数:超级).但是,如果函数期望KClass< out Base&gt ;,那么您也可以传递KClass< Derived&gt ;,因为它满足上述要求:它返回Derived从其应返回Base或其子类型的方法中得出(但对于KClass<超级).并且,相反,期望KClass< Base>的函数被设置为0.也可以接收KClass< Super>

因此,当您重写getCauseIfAssignableFrom以接受ae:KClass< Throwable>中的状态时,您声明在实现中希望能够将Throwable传递给某些通用函数或e的属性,并且需要一个具有以下功能的KClass实例:处理. Any :: class或Throwable :: class都适合,但这不是您所需要的.

由于您不调用e的任何函数,也不访问其任何属性,因此甚至可以将其类型设置为KClass< *>. (明确指出您不在乎类型是什么,并允许它为任何类型),它将起作用.

但是您的用例要求您将类型限制为Throwable的子类型.这是KClass< out Throwable>起作用:将类型参数限制为Throwable的子类型(再次,您声明,对于返回T的KClass< T>的函数和属性或带有T的某些函数(如Function< T>),您想使用返回值好像T是Throwable的子类型;尽管您没有这样做).

适用于您的另一个选项是定义上限< T:Throwable>.这类似于< out Throwable&gt ;,但是它另外捕获了KClass< T>的type参数.并允许您在签名的其他地方(返回类型或其他参数的类型)或实现内部使用它.

标签:kotlin,generics,covariance,java
来源: https://codeday.me/bug/20191025/1931315.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有