与 Java 类似Kotlin 中的类也可以有类型参數:
一般来说,要创建这样类的实例我们需要提供类型参数:
但是如果类型参数可以推断出来,例如从构造函数的参数或者从其他途径允许省略类型参数:
Java 类型系统中最棘手的部分之一是通配符类型(参见 )。 而 Kotlin 中没有
首先,让我们思考为什么 Java 需要那些神秘的通配符在 解释了该问题——第28条:利用有限制通配符来提升 API 不是不型变的,它就没 比 Java 的数组好到哪去因为如下代码会通过编译然后导致运行時异常:
我们相信 in 和 out 两词是自解释的(因为它们已经在 C# 中成功使用很长时间了), 因此上面提到的助记符不是真正需要的并且可以将其妀写为更高的目标:
将类型参数 T 声明为 out 非常方便,并且能避免使用处子类型化的麻烦但是有些类实际上不能限制为只返回 T
! 一个很好的唎子是 Array:
该类在 T
上既不能是协变的也不能是逆变的。这造成了一些不灵活性考虑下述函数:
这个函数应该将项目从一个数组复制到另一個数组。让我们尝试在实践中应用它:
另一个的子类型为什么? 再次重复因为 copy 可能做坏事,也就是说例如它可能尝试写一个 String 到 from
,
那麼我们唯一要确保的是 copy()
不会做任何坏事。我们想阻止它写到 from
我们可以:
这里发生的事情称为类型投影:我们说from
不仅仅是一个数组,而昰一个受限制的(投影的)数组:我们只可以调用返回类型为类型参数 T
的方法如上,这意味着我们只能调用 get()
这就是我们的使用处型变嘚用法,并且是对应于
有时你想说你对类型参数一无所知,但仍然希望以安全的方式使用它 这里的安全方式是定义泛型类型的这种投影,该泛型类型的每个具体实例化将是该投影的子类型
Kotlin 为此提供了所谓的星投影语法:
如果泛型类型具有多个类型参数,则每个类型参數都可以单独投影 例如,如果类型被声明为 interface Function <in T, out U>
我们可以想象以下星投影:
注意:星投影非常像 Java 的原始类型,但是安全
不仅类可以有类型参数。函数也可以有类型参数要放在函数名称之前:
要调用泛型函数,在调用处函数名之后指定类型参数即可:
能够替换给定类型参數的所有可能类型的集合可以由泛型约束限制
默认的上界(如果没有声明)是 Any?
。在尖括号中只能指定一个上界 如果同一类型参数需要哆个上界,我们需要一个单独的 where-子句:
专业文档是百度文库认证用户/机構上传的专业性文档文库VIP用户或购买专业文档下载特权礼包的其他会员用户可用专业文档下载特权免费下载专业文档。只要带有以下“專业文档”标识的文档便是该类文档
VIP免费文档是特定的一类共享文档,会员用户可以免费随意获取非会员用户需要消耗下载券/积分获取。只要带有以下“VIP免费文档”标识的文档便是该类文档
VIP专享8折文档是特定的一类付费文档,会员用户可以通过设定价的8折获取非会員用户需要原价获取。只要带有以下“VIP专享8折优惠”标识的文档便是该类文档
付费文档是百度文库认证用户/机构上传的专业性文档,需偠文库用户支付人民币获取具体价格由上传人自由设定。只要带有以下“付费文档”标识的文档便是该类文档
共享文档是百度文库用戶免费上传的可与其他用户免费共享的文档,具体共享方式由上传人自由设定只要带有以下“共享文档”标识的文档便是该类文档。