宽广的室外网球场上,学生们正在做发球考试的练习。
「嘿!」女孩左手将球向上轻抛,右手握拍奋力用全身的力量击球。
和羽球重视甩腕的方式不同,网球需要躯干旋转的力量,否则很容易受伤。
球网对面的练习搭挡迅速捡球发回,这次换成女孩紧盯着球的飞行抛物线。
「幸好发球规则有指定落点要在对角发球区,双人练习就不用来回奔波。」诗忆松了口气,弯腰把还在滚动的球捡起来。「嗯?这麽说起来,函式参数不是一开始就要指定类别吗?那Collections
的add
函式是怎麽设计成可以根据成员类别弹性变化?」
她一边思考一边发球,一不留神就把球打出了界外,最後收到了搭挡的愤怒警告,她只好先甩开脑里的困惑,毕竟球场上到处都是飞球,很危险的。
很快的,又到了晚上的补课时间。
唯心听完诗忆的问题,很高兴她开始深入思考程序的架构。
「你察觉到今天的主题,泛型
的存在了。」唯心用食指指节轻轻敲击白板刚写上的Generics
。「泛型
,就是将类别也当作一种参数宣告,宣告时需要放在大小於符号中间,比如List
就是宣告成List<T>
,要指定T
的时候则用List<String>
、List<Drink>
等的写法。」
//可以变动的饮料清单
val drinks: MutableList<Drink>
为了更详尽的说明,她打开标准函式库里的List
的程序码档案给诗忆参考。「对了,泛型
参数名字不一定要用Type
的T
,像有些文件写的是List<E>
,E
来自Elements
。另一个常用的名字是Result
的R
。」
public interface List<out E> : Collection<E> {
/**
* Returns the element at the specified index in the list.
*/
public operator fun get(index: Int): E
/**
* Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive).
* The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
*
* Structural changes in the base list make the behavior of the view undefined.
*/
public fun subList(fromIndex: Int, toIndex: Int): List<E>
}
「你看,因为宣告了List<out E>
,所以取得里面的元素就可以宣告成public operator fun get(index: Int): E
。」唯心指了指其中最简单的函式。
「学姐,可是我看程序码里不是List<E>
而是List<out E>
?」诗忆马上发现了问题。
「喔,List<E>
就是List<out E>
和List<in E>
的联集,out
的意思是限定函式只能把该泛型放在回传的位置,in
是限定函式把该泛型放在参数的位置。所以可以变动成员的MutableList<E>
就还需要支援in
的部分。」唯心将List.kt
的程序码向下滚动到MutableList
的部分。
public interface MutableList<E> : List<E>, MutableCollection<E> { /**
* Adds the specified element to the end of this list.
*
* @return `true` because the list is always modified as the result of this operation.
*/
override fun add(element: E): Boolean
override fun remove(element: E): Boolean
}
唯心瞥了一眼手上的讲义,补充说。「而如果要支援多个泛型,和函式参数一样,用逗号分隔。此外,泛型也可以限定范围,比如说希望都是继承某个类别的类型或介面。」
public interface Sample<T : 某个可继承的类型或介面, R> {
}
诗忆往前翻了翻继承和介面相关的笔记。「之前说类别可以扩展多个介面,那泛型也可以限定多个介面吗?」
「可以,不过语法比较复杂,课堂上没特别提,我也没怎麽用过,我找找官网文件唷。」唯心很快找到了说明泛型
的页面。「要用where
描述,这里有个范例可以参考。」
https://kotlinlang.org/docs/generics.html#upper-bounds
fun <T> copyWhenGreater(list: List<T>, threshold: T): List<String>
where T : CharSequence,
T : Comparable<T> {
return list.filter { it > threshold }.map { it.toString() }
}
<<: Day10 - 子元件透过 emit event 触发父元件事件
>>: 连续 30 天 玩玩看 ProtoPie - Day 9
介绍Jenkins的章节即将进入尾声了。事实上你可能会想Jenkins默认介面这麽老气,怎麽就成为全...
前面几天我们已经用 TDD 的方式完成了 <Editor /> 元件,但不要忘了 TDD...
Python基础语法 列印讯息 print(“所输入的讯息”, 变数名称) 这是一个会将输入的讯息所...
FloatButton和Snackbar FloatButton是漂浮式按钮,也可以说是不同种设计的...
咱们一起做资料清理和前处理 今日学习目标 资料如何清理 什麽是资料清理? 资料前处理的方式 为什麽资...