本文首發於 Ficow Shen's Blog,原文地址: Swift self, Self, ==, === 傻傻分不清楚?。html
前言面試
self
和 Self
swift
==
和 ===
ide
總結函數
在2014年開源以後,Swift就在飛速地茁壯成長,內涵也愈來愈豐富。post
對於實際使用Swift的人來講,概念多了就比較容易混淆😨,而後就會致使開發效率低下。畢竟,你須要去查這些概念的正肯定義,或者你須要去寫代碼進行驗證。self, Self, ==, === 就是比較典型的例子。ui
在面試別人的過程當中,我發現有不少朋友分不清楚這些概念。因此,我打算根據我本身的理解來梳理一下這些概念,但願可以幫你們少走一些彎路。🌟🌟🌟指針
self
和 Self
self
首先,最簡單的確定是實例中的 self
了:code
如上圖所示,Xcode 會告訴你這個 self
屬於 TestClass
類型。htm
self
:如上圖所示,Xcode 會告訴你這個 self
是 TestClass.Type
類型。稍等一下,.Type
是什麼東西?
從字面意思去理解,這個 self
是 TestClass
這個類型自己。
若是爲該類型定義一個靜態常量(static let
),咱們就能夠在類型的靜態方法(static func
)中去訪問這個靜態常量。由於,它們都屬於這個類型自己。self.classLet
也就是在訪問 TestClass
這個類型自己的常量 classLet
。
Self
請看,咱們能夠直接經過 Self
去訪問類型上的屬性:
可是,這個 Self
不等於 self
。
上圖中的 print
函數會打印 true
。爲何呢?
請推測一下,print(TestClass.self == self)
會打印 true
仍是 false
?
請不要中止思考,更有意思的來了😹:
請問,這些 print
會分別打印什麼內容?
好吧,結果是 3 行 true
。因此, 這個 Self
等同於當前這個實體類型,對嗎?
抱歉,不對!!!🤭 根據 官方文檔 的內容,這個 Self
的值等於 type(of: self)
。也就是說,這個值是動態獲取的!
如今,讓咱們來看一個示例:
class TestClass { static let classLet = 0 let instanceLet = classLet // 不能寫成 self.classLet var instanceVar = classLet lazy var instanceLazyVar = Self.classLet // 不能寫成 self.classLet }
若是須要用類型中的屬性來初始化實例中的屬性,就能夠參考上面這種方法。注意,不能寫成 let instanceLet = self.classLet
。這樣寫會出現編譯錯誤,self
是未定義的。
若是使用懶加載的屬性,要注意區分 self
和 Self
。由於實例已經完成了初始化,此時 self
是有效的。
若是將 Self
用在協議中,好比:
protocol TestProtocol { func getSelf() -> Self } class TestBaseClass: TestProtocol { func getSelf() -> Self { return self } } class TestSubclass: TestBaseClass { override func getSelf() -> Self { return self } } let base: TestBaseClass = TestBaseClass() let sub: TestSubclass = TestSubclass()
此時,Self
是最終實現協議的那個類型。
==
和 ===
==
Equatable
協議中定義的方法:static func == (lhs: Self, rhs: Self) -> Bool
;!=
;示例:
class MyType: Equatable { let id: UUID let name: String init(id: UUID, name: String) { self.id = id self.name = name } static func == (lhs: MyType, rhs: MyType) -> Bool { // lhs: left-hand side, rhs: right-hand side // 也能夠是: return lhs.id == rhs.id,規則由你來定義 return lhs.id == rhs.id && lhs.name == rhs.name } } // 還能夠這樣定義: class MyType: Equatable { let name: String init(name: String) { self.name = name } static func == (lhs: MyType, rhs: MyType) -> Bool { // ObjectIdentifier 不支持值類型 // 也能夠這樣比較: return lhs === rhs return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) } }
===
!==
;示例:
NSObject() === NSObject()
相關文檔:
Equivalence Operators(==)
Identity Operators(===)
這些是比較經常使用並且比較基礎的語法知識點,咱們要爭取理解到位,不然就會影響到開發效率。
這是 Swift 的 Revision History(文檔修訂歷史),建議你們多關注。好比 SwiftUI
中最多見的 some
關鍵字就是在 Swift 5.1 中新增的 Opaque Types
。在掌握新特性的同時,不按期地去溫習舊的基礎知識,這樣能夠有效地保證本身的認知沒有與現實脫節~
以上就是本文的所有內容,若有謬誤,麻煩幫我指出。 若是你也有推薦閱讀的內容,請留言告訴我,你們共同進步!謝謝~ 🤗