44-泛型-函数
泛型概述
在仓颉编程语言中,泛型指的是参数化类型,参数化类型是一个在声明时未知并且需要在使用时指定的类型。类型声明与函数声明
可以是泛型的。最为常见的例子就是 Array<T>
、Set<T>
等容器类型。以数组类型为例,当使用数组类型 Array
时,会需要
其中存放的是不同的类型,我们不可能定义所有类型的数组,通过在类型声明中声明类型形参,在应用数组时再指定其中的类型,
这样就可以减少在代码上的重复。
在仓颉中,class、interface、struct 与 enum 的声明都可以声明类型形参,也就是说它们都可以是泛型的。
泛型函数概念
如果一个函数声明了一个或多个类型形参,则将其称为泛型函数。语法上,类型形参紧跟在函数名后,并用 <>
括起,如果有多个类型形参,则用“,”分离。
按照使用场景,可以将泛型函数分类以下种类:
- 全局泛型函数
- 局部泛型函数
- 泛型成员函数
- 静态泛型函数
全局泛型函数
如果一个函数声明了一个或多个类型形参,则将其称为泛型函数。语法上,类型形参紧跟在函数名后,并用 <>
括起,如果有多个类型形参,则用“,”分离。
func id<T>(a: T): T {
return a
}
main() {
let res = id<Int64>(100) // 100
}
其中 (a: T)
是函数声明的形参,其中使用到了 id
函数声明的类型形参 T
,并且在 id
函数的返回类型使用。
再来复杂例子:
func composition<T1, T2, T3>(f: (T1) -> T2, g: (T2) -> T3): (T1) -> T3 {
return {x: T1 => g(f(x))}
}
func times2(a: Int64): Int64 {
return a * 2
}
func plus10(a: Int64): Int64 {
return a + 10
}
func times2plus10(a: Int64) {
return composition<Int64, Int64, Int64>(times2, plus10)(a)
}
main() {
println(times2plus10(9))
return 0
}
局部泛型函数
局部函数也可以是泛型函数。例如泛型函数 id
可以嵌套定义在其它函数中:
func foo(a: Int64) {
func id<T>(a: T): T { a }
func double(a: Int64): Int64 { a + a }
return (id<Int64> ~> double)(a) == (double ~> id<Int64>)(a)
}
main() {
println(foo(1))
return 0
}
这里由于 id
的单位元性质,函数 id<Int64> ~> double
和 double ~> id<Int64>
是等价的,结果是 true
。
true
泛型成员函数
class、struct 与 enum 的成员函数可以是泛型的。例如:
class A {
func foo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
struct B {
func bar<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
enum C {
| X | Y
func coo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
main() {
var a = A()
var b = B()
var c = C.X
a.foo<Int64>(10)
b.bar<String>("abc")
c.coo<Bool>(false)
return 0
}
程序输出的结果为:
10
abc
false
这里需要注意的是,class 中声明的泛型成员函数不能被 open 修饰,如果被 open 修饰则会报错,例如:
class A {
public open func foo<T>(a: T): Unit where T <: ToString { // Error, open generic function is not allowed
println("${a}")
}
}
在为类型使用 extend 声明进行扩展时,扩展中的函数也可以是泛型的,例如我们可以为 Int64
类型增加一个泛型成员函数:
extend Int64 {
func printIntAndArg<T>(a: T) where T <: ToString {
println(this)
println("${a}")
}
}
main() {
var a: Int64 = 12
a.printIntAndArg<String>("twelve")
}
程序输出的结果将为:
12
twelve
静态泛型函数
interface、class、struct、enum 与 extend 中可以定义静态泛型函数,例如下例 ToPair
class 中从 ArrayList
中返回一个元组:
import std.collection.*
class ToPair {
public static func fromArray<T>(l: ArrayList<T>): (T, T) {
return (l[0], l[1])
}
}
main() {
var res: ArrayList<Int64> = ArrayList([1,2,3,4])
var a: (Int64, Int64) = ToPair.fromArray<Int64>(res)
return 0
}