import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//泛型
//泛型代码可以让你写出根据自我需求定义、适用于任何类型的,零活可重用的函数和类型。可以避免重复的代码。
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, b: &anotherInt)
print("\(someInt) \(anotherInt)")//107 3
var somestr="hello"
var anotherString="world"
swapTwoValues(&somestr, b: &anotherString)
print("\(somestr) \(anotherString)")
//请始终使用大写字母开头的驼峰式命名法(例如:T 和 Key)来给类型参数命名,以表明它们是类型的占位符,而非类型值。
//通常在泛型函数中,swift允许你定义你自己的泛型类型。这些自定义类、结构体和枚举作用于任何类型,如同array和dictionary的用法
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cua")
stackOfStrings.pop()
print(stackOfStrings.items);//["uno", "dos", "tres"]
//扩展一个泛型类型
//原始类型定义中声明的类型参数列表在扩展中是可以使用的。并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用
if let topItem = stackOfStrings.topItem{
print("The Top Item is \(topItem)")//The Top Item is tres
}
//类型约束
//func someFunction<T:SomeClass,U:SomeProtocol>(someT:T,someU:U){//这里是函数主体}
//第一个类型参数T,有一个需要T必须是SomeClass子类的类型约束;第二个类型参数U,需要U必须遵循SomeProtocol协议的类型约束。
let strings = ["cat","dog","llama","hhhh","oooo"]
if let foundIndex = findStringIndex(strings, "dog")
{
print("The index of dog is \(foundIndex)")
}//The index of dog is 1
if let doubleIndex = findIndex([3.14159,0.1,0.25], 0.25){
print("The index of 0.25 is \(doubleIndex)")
}//The index of 0.25 is 2
if let stringIndex = findIndex(["Mike","Malcolm","Andrea"], "Andrea"){
print("The index of Andrea is \(stringIndex)")
}//The index of Andrea is 2
//关联类型
//当定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分是非常有用的。一个关联类型作为协议的一部分,给定了类型的一个占位名(或别名)。关联类型被指定为typealias关键字
//where 语句
//类型约束能够确保类型符合泛型函数或类的定义约束。
var stackOfStrings2 = myStack<String>()
stackOfStrings2.push("one")
stackOfStrings2.push("two")
stackOfStrings2.push("three")
let arrayOfStrings = ["one","two","three"]
if allItemsMatch(stackOfStrings2, anotherContainer: arrayOfStrings){
print("ALL items match")
}else{
print("Not all items match")
}//ALL items match
}
//swift标准库中定义了一个Equatable协议,该协议要求任何遵循的类型实现等式符(==)和不等式符(!=)对任何俩个该类型进行比较。
//findIndex中这个单个类型参数写做:T: Equatable,也就意味着“任何T类型都遵循Equatable协议”
func findIndex<T: Equatable>(array:[T],_ valueToFind:T)->Int?{
for (index,value) in array.enumerate(){
if value == valueToFind{//不是所有的swift中的类型都可以用等式符进行比较。
return index
}
}
return nil
}
func findStringIndex(array:[String], _ valueToFind:String)->Int?{
for (index,value) in array.enumerate(){
if value == valueToFind{
return index
}
}
return nil
}
func swapTwoValues<T>(inout a:T,inout b:T){//通过占位类型T(也可以用其它字符或字符串)来代替实际类型名
let temporary = a
a = b
b = temporary
}
func swapTwoInts(inout a:Int,inout b:Int){
let temporary = a
a = b
b = temporary
}
func swapTwoStrings(inout a:String,inout b:String){
let temporary = a
a = b
b = temporary
}
}
//使用where语句,紧跟在类型参数列表后面,where语句后跟一个或多个针对关联类型的约束,以及一个或多个类型和关联类型间的等价关系,
func allItemsMatch <C1: Container,C2: Container
where C1.ItemType: Equatable , C1.ItemType==C2.ItemType > (someContainer:C1,anotherContainer:C2)->Bool{
//检查两个Container的元素个数是否相同
if someContainer.count != anotherContainer.count{
return false
}
for i in 0..<someContainer.count{
if someContainer[i] != anotherContainer[i]{
return false
}
}
//如果所有元素检查都相同则返回true
return true
}
extension Array: Container{}//swift的Array已经提供append方法,一个count属性和通过下标来查找一个自己的元素。这三个功能都达到Container协议的要求。也就意味着可以扩展Array去遵循Container协议,定义了这个扩展后,可以将任何Array当作Container来使用。
// 关联类型实例
protocol Container{
typealias ItemType
mutating func append(item:ItemType)
var count:Int{get}
subscript(i:Int)->ItemType{get}
}
struct myStack<T>:Container {
var items = [T]()
mutating func push(item:T){
items.append(item)
}
mutating func pop()->T{
return items.removeLast()
}
mutating func append(item: T) {
self.push(item)
}
var count :Int{
return items.count
}
subscript(i:Int)->T{
return items[i]
}
}
struct myIntStack:Container {
var items = [Int]()
mutating func push(item:Int){
items.append(item)
}
mutating func pop()->Int{
return items.removeLast()
}
//遵循Container协议的实现
typealias ItemType = Int //将抽象的ItemType类型转换为具体的Int类型
mutating func append(item: Int) {
self.push(item)
}
var count : Int{
return items.count
}
subscript(i:Int)->Int{
return items[i]
}
}
extension Stack{
var topItem:T?{
return items.isEmpty ? nil:items[items.count-1]
}
}
//泛型版本
struct Stack <T> {//泛型版本的占位类型参数为T替代了实际Int类型。这种类型参数包含一对尖括号紧随在结构体名字后面
var items=[T]()
mutating func push(item:T){
items.append(item)
}
mutating func pop() -> T{
return items.removeLast()
}
}
//非泛型版本的栈,Int值型的栈
struct IntStack {
var items = [Int]()
mutating func push(item:Int){
items.append(item)
}
mutating func pop()->Int{
return items.removeLast()
}
}