型別別名
型別別名(Type aliases)為現有型別提供替代名稱。 如果型別名稱太長,你可以引入另一個較短的名稱並改用新名稱。
這對於縮短長泛型型別非常有用。 例如,通常會想要縮減集合型別:
kotlin
typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K, MutableList<File>>你可以為函式型別提供不同的別名:
kotlin
typealias MyHandler = (Int, String, Any) -> Unit
typealias Predicate<T> = (T) -> Boolean你可以為內部類別和巢狀類別建立新名稱:
kotlin
class A {
inner class Inner
}
class B {
inner class Inner
}
typealias AInner = A.Inner
typealias BInner = B.Inner型別別名不會引入新型別。 它們與對應的底層型別等價。 當你加入 typealias Predicate<T> 並在程式碼中使用 Predicate<Int> 時,Kotlin 編譯器始終會將其展開為 (Int) -> Boolean。 因此,只要需要通用函式型別,你就可以傳遞該型別的變數,反之亦然:
kotlin
typealias Predicate<T> = (T) -> Boolean
fun foo(p: Predicate<Int>) = p(42)
fun main() {
val f: (Int) -> Boolean = { it > 0 }
println(foo(f)) // prints "true"
val p: Predicate<Int> = { it > 0 }
println(listOf(1, -2).filter(p)) // prints "[1]"
}巢狀型別別名
在 Kotlin 中,只要型別別名不從其外層類別擷取型別參數,你就可以在其他宣告中定義型別別名:
kotlin
class Dijkstra {
typealias VisitedNodes = Set<Node>
private fun step(visited: VisitedNodes, ...) = ...
}「擷取」是指型別別名引用了在外層類別中定義的型別參數:
kotlin
class Graph<Node> {
// 錯誤,因為擷取了 Node
typealias Path = List<Node>
}要修正此問題,請直接在型別別名中宣告型別參數:
kotlin
class Graph<Node> {
// 正確,因為 Node 是型別別名參數
typealias Path<Node> = List<Node>
}巢狀型別別名透過改進封裝、減少套件層級的混亂並簡化內部實作,讓程式碼更簡潔、更易於維護。
巢狀型別別名的規則
巢狀型別別名遵循特定規則,以確保行為清晰且一致:
- 巢狀型別別名必須遵循所有現有的型別別名規則。
- 就可見性而言,別名不能暴露比其引用的型別所允許更多的內容。
- 它們的作用域與 巢狀類別 相同。你可以在類別內部定義它們,它們會隱藏任何同名的父級型別別名,因為它們不會覆寫。
- 巢狀型別別名可以標記為
internal或private以限制其可見性。 - Kotlin 多平台的
expect/actual宣告 不支援巢狀型別別名。
