ios 可以为空声明_iOS开发中使用OC和swift的对比(2)
OC與swift
1.協(xié)議
OC:主要用來傳值
swift:不僅可以用來傳值,swift中的協(xié)議可以定義屬性方法,并且其協(xié)議可以進(jìn)行擴(kuò)展,在擴(kuò)展中還可以有自己的默認(rèn)實(shí)現(xiàn),這個(gè)特性使其可以面向協(xié)議的時(shí)候非常強(qiáng)大。
例:
//如果遵守了swift中的協(xié)議,那么里邊的非擴(kuò)展方法必須實(shí)現(xiàn) protocol AnimationProtocol {//最大年齡(屬性方法)var maxAge: Int {get}//動(dòng)物都有自己的名字func name() }//swift中的協(xié)議支持?jǐn)U展,并且可以再擴(kuò)展中直接實(shí)現(xiàn)具體內(nèi)容(擴(kuò)展中不可以定義屬性方法),似乎跟OC中的繼承一樣 extension AnimationProtocol {func eat() {print("eat");} }class Dog: AnimationProtocol {//maxAge必須實(shí)現(xiàn)var maxAge: Int {get {return 20}}//name必須實(shí)現(xiàn)func name() {print("name: dog")}//可以實(shí)現(xiàn)也可以省略(類似繼承中的復(fù)寫)func eat() {print("eat shit")}}class Cat: AnimationProtocol {var maxAge: Int {get {return 10}}func name() {print("name: cat")} }使用繼承很容易出現(xiàn)父類越來越臃腫特別是多重繼承時(shí),最終變成方法垃圾場的情況;
但是利用swift的協(xié)議,可以實(shí)現(xiàn)類似于繼承的功能,但是比繼承更加靈活;當(dāng)某幾個(gè)類有共同特性的時(shí)候可以抽出一個(gè)協(xié)議,使用的時(shí)候遵守此協(xié)議即可,可以解放父類。
2.泛型
泛型在很多功能上看似可以用多態(tài)實(shí)現(xiàn),但還是有很多區(qū)別的。
自己目前為止的看法,如下是使用泛型的例子:
static func set<T>(_ key: String, value: T) {let stdDefaults = UserDefaults.standardstdDefaults.set(_T<Any>.cast(value), forKey: key)stdDefaults.synchronize()}static func get<T>(_ key: String) -> T? {let stdDefaults = UserDefaults.standardlet value: Any? = stdDefaults.value(forKey: key)return _T<T>.cast(value)}那么如果將泛型改為多態(tài),如下:
static func set(_ key: String, value: Any) {let stdDefaults = UserDefaults.standardstdDefaults.set(value, forKey: key)stdDefaults.synchronize()}static func get(_ key: String) -> Any? {let stdDefaults = UserDefaults.standardlet value: Any? = stdDefaults.value(forKey: key)return value}會(huì)有什么問題呢?
一個(gè)簡單的例子,如果我獲取的是一個(gè)model,那么如果是多態(tài),使用應(yīng)該是這樣的:
let model = Model()SDB.set("model", value: model)let md = SDB.get("model") as? Model //使用了as?說明這是類型轉(zhuǎn)換如果是泛型,使用應(yīng)該是這樣的:
SDB_T.set("model", value: model)let md_t: Model? = SDB_T.get("model") //前邊添加類型,屬于泛型的特征類型推斷//static func get<T>(_ key: String) -> T?類型推斷是swift特有的,比如說let str = "",swift可以推斷出str為String類型
下邊是一個(gè)項(xiàng)目中很有用的自定義去重算法:
//去重算法 Equatable 判等協(xié)議func removalAlgorithm<T: Equatable>(a: [T], b:T) -> [T] {var items = afor i in 0..<a.count {let item = a[i]if item == b {items.remove(at: i)}}return items}而mode中所要實(shí)現(xiàn)的協(xié)議如下:
class Model: Equatable {var mId: Int?var a: String?static func == (lhs: Model, rhs: Model) -> Bool {if lhs.mId == rhs.mId {return true}return false} }上邊的方法,如果不用泛型,想使用可能就比較麻煩了,需要各種類型轉(zhuǎn)換。
3.結(jié)構(gòu)體和類
oc和swift中結(jié)構(gòu)體何磊的類型是相同的,即結(jié)構(gòu)體是值類型,class是指針類型。
但是swift中結(jié)構(gòu)體更強(qiáng)大,可以實(shí)現(xiàn)很多類似于類的功能,目前swift中的Array,Dictory,String均為結(jié)構(gòu)體,因此這些常用的數(shù)據(jù)類型用法有比較大的差異。
String為例:
OC中兩個(gè)字符串對象是不可以直接用==進(jìn)行比較的,但是swift就可以(數(shù)組,字典同理)。
既然是值類型,那么有些運(yùn)算符就可以直接使用,如+:
4.?&!
swift是類型確定型語言,對類型是否有值有嚴(yán)格要求,因此引入了?和!來對值進(jìn)行明確。
oc中如下:
這樣寫在oc中是完全沒有問題的,但是使用者可能就比較麻煩了,因?yàn)橥獠渴褂谜卟⒉荒艽_定這個(gè)有沒有值,因此每個(gè)使用此方法的人都需要去判斷返回值是否符合自己預(yù)期;
swift中如下:
func test() ->String {//錯(cuò)誤的寫法,編譯器會(huì)報(bào)錯(cuò)return nil}這樣寫在swift中是會(huì)報(bào)錯(cuò)的,因?yàn)槟愕姆祷刂礢tring沒有帶?因此默認(rèn)是一個(gè)非空的,所以此函數(shù)的作者就需要去考慮如果這兒是空或者這兒的類型不是我想要的,我要做哪些補(bǔ)救措施,其實(shí)就是從源頭上對一些錯(cuò)誤特別是野指針問題做了預(yù)防。
那么在swift中怎么正確使用這一特性呢?
1.在某些場景下,你確定此函數(shù)會(huì)返回一個(gè)有效值,那么你就可以在返回值后邊加!或者默認(rèn)不加;
2.有時(shí)候我們就是要告訴外邊,這個(gè)不一定是有效的,需要外部使用者自己處理,那就在返回值后便加?;
5.??
swift中多了一種??判斷符,它的作用類似三元運(yùn)算符,但是使用場景比較多的地方是對一個(gè)為空的值做詢問,如果為空怎么怎么樣,如下:
func test(_ a :String?) ->String? {//如果a為空,則返回空字符串(其實(shí)這樣寫,返回值已經(jīng)不可能為空了)return a ?? ""}作者:wordlesser
鏈接:https://www.jianshu.com/p/818539a539e4 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的ios 可以为空声明_iOS开发中使用OC和swift的对比(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Git 的工作区、暂存区、版本库—— G
- 下一篇: git checkout 命令详解——