/* 范型 Generics C++中的模版函数,模板类
1.范型函数
2.Generic Type
3.范型类型的扩展
4.范型类型约束(给T加一个约束,不是所有类型都可以用)
5.用typealias定义范型
6.可以用where语句来对类型参数列表进行限制
*/
//1.范型函数
func testGenerics<MyType1, MyType2>(para1: MyType1, para2: MyType2)
{
//由于println本身是范型的,这里为了简单说明直接这样测试
println(para1)
println(para2)
}
testGenerics("hello", 3)
testGenerics("hello", "Hello2")
//2.范型类型 可以是类,结构体,枚举等
// 堆栈的例子,这里为了将重点放在范型类型上,没有容错
struct Stack<T>
{
var items = [T]()
mutating func push(newitem: T)
{
println("Push a newitem \(newitem)")
self.items.append(newitem)
}
mutating func pop() -> T
{
println("pop a item")
return self.items.removeLast()
}
}
//类型的创建实例,可以看到之前数组Array<Int>(),Dictionary<keyType,valueType>()都是范型
var s = Stack<Int>() //函数范型在调用的时候不需要带类型,但是类型需要带
s.push(3)
s.pop()
//3.范型类型的扩展,不需要向定义一样需要提供类型T(类型参数列表),直接用就可以。
extension Stack
{
var topItem: T?{
return items.isEmpty ? nil : items[items.count - 1]
}
}
//4.范型类型约束
//下面这个函数定义了类型参数列表的约束,T必须是SomeCLass的子类,U必须是某协议的遵循者
//Generic Type的定义方法和这个类似
//func someFunction<T: SomeClass, U: SomeProtocol>(para1: T, para2: U){ }
func findIndex<T>(array:[T], value:T, isEqual:(T, T)->Bool)->Int? {
for (index, item) in enumerate(array) {
if isEqual(item, value) {
return index
}
}
return nil
}
//上面的函数如果要求类型T必须遵循系统库协议Equatable,即可以用==进行比较的协议,就会简单一些
func findIndex2<T: Equatable>(array: [T], value:T) -> Int? {
for (index, item) in enumerate(array) {
if item == value {
return index
}
}
return nil
}
//5.用typealias创建范型协议
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int)->ItemType { get }
}
class IntStack: Container {
var items = [Int]()
func push(item: Int) {
items.append(item)
}
func pop() -> Int {
return items.removeLast()
}
// typealias ItemType = Int在实现的时候可以不定义,swift可以自行推导出。
typealias ItemType = Int
func append(item: ItemType) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
// 用where语句对类型参数列表进行限制
//Array已经有Container的方法,但是并不是Container的遵循者,加上用于下面的测试
extension Array: Container{}
func allItemsMatch<C1:Container, C2:Container where C1.ItemType == C2.ItemType,
C1.ItemType:Equatable> (container1: C1, container2: C2)->Bool {
if container1.count != container2.count
{
return false
}
for i in 0..<container1.count {
if container1[i] != container2[i] {
return false
}
}
return true
}
var a1 = [1,2,3]
var a2 = ["ok", "hi", "test"]
allItemsMatch(a1, a2) //ERROR 在函数定义时,要求两个类型需要一致,这里不同会报错。