iOS学习开发

Swift的编程利器-泛型

2019-05-09  本文已影响124人  howard0103

引言

在搭建项目框架时,我们通常会写很多通用代码。通用代码就必须要求灵活性和扩展性了。比如有两个非常相似的模块,只是一个是处理int类型,另一个处理string类型,或者是其它数据类型,当然我们可以分别写不同的方法来分别处理,也可以在一个方法里面用if-elseif来分别处理。但这样的代码太复杂,灵活性和扩展性都不高。要解决这个问题怎么办呢?
泛型就是为了解决这个问题产生的。很多编程语言里都有泛型,在做Android项目时就使用过java语言里的泛型,当时就感觉非常友好,灵活非常高。
今天我们来聊聊swift语言中的泛型,oc语言中本来是没有泛型的,新的xcode在swift的影响下才给oc加入了泛型并且也是伪泛型。

swift泛型

为什么要使用泛型

泛型是为了编程更加的灵活,避免重复的代码,清晰和抽象的方式来表达代码的意图。
为了解释这句话,下面举个简单的例子来说明
场景一:写一个方法把Int变量A和Int变量B的值交换一下

//1 定义一个方法
func exchange(a: Int, b:Int) {
    let temp = a
    a = b
    b = temp
}
//2 具体使用
var oneInt = 1
var twoInt = 2
exchange(a:&oneInt, b:&twoInt)
print("oneInt= \(oneInt), twoInt= \(twoInt)") //打印: oneInt=2,twoInt=1

场景二:写一个方法把String变量A和String变量B的值交换一下

//1 定义一个方法
func exchange(a: String, b:String) {
    let temp = a
    a = b
    b = temp
}
//2 具体使用
var oneStr= "str1"
var twoStr= "str2"
exchange(a:&oneStr, b:&twoStr)
print("one= \(oneStr), twoStr= \(twoStr)") //打印: oneStr=str2,twoStr=str1

大家想必已经发现问题了吧,场景一和场景二非常的类似,只是处理的数据类型不一样,如果还想处理其它数据类型呢?这样实现就太复杂了。
使用泛型便可解决这个问题。

我们来看看利用泛型是如何实现的

//1 定义一个泛型方法
func exchange<T>(a: T, b:T) {
    let temp = a
    a = b
    b = temp
}
//2 具体使用
var oneInt = 1
var twoInt = 2
exchange(a:&oneInt, b:&twoInt)
print("oneInt= \(oneInt), twoInt= \(twoInt)") //打印: oneInt=2,twoInt=1

var oneStr= "str1"
var twoStr= "str2"
exchange(a:&oneStr, b:&twoStr)
print("one= \(oneStr), twoStr= \(twoStr)") //打印: oneStr=str2,twoStr=str1

定义一个方法,随意使用,太棒了!

泛型 vs Any

泛型可以指定任意类型,这个时候大家应该会联想到Any,Any也是可以指定任意类型的,话不多说,先上一段代码,大家来看看他们的区别

//函数一
func method1<T>(a: T, b: T) ->T {
     ...
}
//函数二
func method2(a: Any, b: Any) ->Any {
     ...
}

看到他们的区别了吧
相同之处:
a,b参数类型和返回值类型都可以是任意类型
不同之处:
函数一中a,b两参数和返回值类型必须是同一类型T
函数二中a,b两参数和返回值类型都可以是任意类型,不一定相同
为什么会这样呢?
因为泛型的类型检查是由编译器负责的,而Any类型则避开了类型检查。
这里便体现了泛型的一大优点:安全性强。
为什么会这样说呢?因为使用泛型程序在编译的时候,就会帮我们发现问题,而使用Any,程序就只有在运行的时候发现问题了。尽量要把Bug消灭在摇篮中呀!

AnyObject?
大家会不会想到AnyObject,其实这个并不是任意类型,它只是用于任何类(class)的实例。比如基本数据类型,值类型就不能用AnyObject来修饰

泛型是如何使用的呢?
func exchange<T>(a: T, b:T) {
     ...
}
struct ClassA<T> {
     var arr = [T]()
     mutating func add(item: T) {
         arr.append(item) 
    }
}
func methodXXX<T: ClassXXX>(param: T) {
     ...
}
protocol MyProtocol {
   //声明一个关联类型,使用associatedtype关键字
   associatedtype ItemType
}
func methodXXX<T1: MyProtocol, T2: MyProtocol where T1.ItemType == T2.ItemType>(param1: T1, param2: T2) {
    ...
}

这里T1和T2都遵循了MyProtocol协议,并且T1和T2包含的泛型类型是一致的

总结

如果有任何问题,或者有什么想法,随时联系我,大家一起交流,共同进步。
我的邮箱 344185723@qq.com

上一篇下一篇

猜你喜欢

热点阅读