/*
泛型: 之前我们介绍数组和可选型的时候, 我们已接触到泛型, 泛型代码可以确保写出灵活的, 可重用的函数
*/
/// 在Swift中, 有参数的函数必须指定参数的类型, 现在有几个同名的函数实现相似的功能, 但是参数的类型不同, 例如:
/*
func show(para:Int) {
print("Hello \(para)")
}
func show(para:String) {
print("Hello \(para)")
}
func show(para:Double) {
print("Hello \(para)")
}
*/
//1.虽然系统可以根据参数类型调用不同的参数, 但在定义上这种方法太过冗余. 泛型所带来的好处就是可以通过定义单个函数来实现上面的功能. 使用泛型作为参数的函数叫做泛型函数, 下面是与上例有相同的泛型函数定义:
func show<T>(para:T) {
print("Hello \(para)")
}
show(para: "小韩哥") // 输出"Hello 小韩哥"
show(para: 12) //输出 "Hello 12"
//2.泛型函数在声明时使用了节点类型命名(通常情况下用字母 T, U, V 这样的大写字母来表示)来代替实际类型名(如: Int, String 或 Double). 节点类型在定义时不表示任何具体类型, 在函数被调用时会根据传入的实际类型来制定自身的类型. 另外需要指出的是, 如果函数的泛型列表只有一个 T, 虽然具体类型不需要指定, 但是每个节点类型的参数必须是相同类型的. 例如:
func show1<T>(para:T,para2:T){}
//在调用这个函数时, 两个参数必须是相同的类型:
show1(para: 1, para2: 2)
show1(para: "小花", para2: "小明")
//3.定义多个不同类型的泛型,则需要在街括号中加入多个节点:<T,U,V> ;
//你可以对节点进行一些限制, 比如要求泛类型遵守某些协议, Swift中数组的判等就是这样定义的:
//public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) ->Bool
//Element 是节点声明的, 它代表一个泛型, 可以看到这里的泛型名是Element, 相比上面的"T","U","V"长的多. 这是因为此处的 Element不仅仅是一个占位符的作用, 它还声明了这个泛型代表数组中的元素类型, 有具体的意义, 这种 API 的设计指的我们借鉴;
//4.有时候节点中的泛型需要有更多的限制, 需要使用 where 子句来补充约束条件:
/*
func anyCommonElements<T : SquenceType, U : SequenceType>(lhs : T, _ rhs : U) -> Bool where
T.Generator.Element: Equatable,
T.Generator.Element == U.Generator.Element{
return false
}
*/
/*
泛型协议
*/
// 这里的Element不仅仅体现泛型的优势, 还隐性的约束了两个方法的参数必须是相同类型的.
protocol SomeProtocol {
associatedtype Element
func elementMethod1(element: Element)
func elementMethod2(element: Element)
}
struct TestStruct:SomeProtocol {
func elementMethod1(element: String) {
print("elementMethod1: \(element)")
}
func elementMethod2(element: String) {
print("elementMethod2: \(element)")
}
}
// 类似于associatedtype的还有 self 关键字, 代表了协议遵守着本身的类型, 适用于比较这类方法, 其必须传入另一个相同类型的参数才有意义:
protocol CanCompare {
func isBigger(other:Self) -> Bool
}
struct BoxInt:CanCompare {
var intValue:Int
func isBigger(other: BoxInt) -> Bool {
return self.intValue > other.intValue
}
}
print(BoxInt(intValue: 3).isBigger(other: BoxInt(intValue: 2))) //true
/*
泛型对象:
*/
struct TestStruct2< T: Comparable > {
func elementMethod3(element:T){
print("elementMethod3:\(element)")
}
func elemetMethod4(element:T){
print("elementMethod4:\(element)")
}
}
let test = TestStruct2<Int>()
test.elementMethod3(element: 1) //elementMethod3:1
//注意:如果你尝试在实现时"嵌套"一