Swift self, Self, ==, === 傻傻分不清楚?


 

本文首發於 Ficow Shen's Blog,原文地址: Swift self, Self, ==, === 傻傻分不清楚?

 

內容概覽

  • 前言

  • selfSelf

  • =====

  • 總結

 

前言

 

在2014年開源之后,Swift就在飛速地茁壯成長,內涵也越來越豐富。

對於實際使用Swift的人來說,概念多了就比較容易混淆😨,然后就會導致開發效率低下。畢竟,你需要去查這些概念的正確定義,或者你需要去寫代碼進行驗證。self, Self, ==, === 就是比較典型的例子。

在面試別人的過程中,我發現有很多朋友分不清楚這些概念。所以,我打算根據我自己的理解來梳理一下這些概念,希望能夠幫大家少走一些彎路。🌟🌟🌟

 

selfSelf

 

實例中的 self

首先,最簡單的肯定是實例中的 self 了:

圖片alt

如上圖所示,Xcode 會告訴你這個 self 屬於 TestClass 類型。

 

類型中的 self

圖片alt

如上圖所示,Xcode 會告訴你這個 selfTestClass.Type 類型。稍等一下,.Type 是什么東西?
從字面意思去理解,這個 selfTestClass 這個類型本身。

圖片alt

如果為該類型定義一個靜態常量(static let),我們就可以在類型的靜態方法(static func)中去訪問這個靜態常量。因為,它們都屬於這個類型本身。self.classLet 也就是在訪問 TestClass 這個類型本身的常量 classLet

 

實體類型(concrete type)中的 Self

請看,我們可以直接通過 Self 去訪問類型上的屬性:

圖片alt

但是,這個 Self 不等於 self

圖片alt

上圖中的 print 函數會打印 true。為什么呢?

圖片alt

請推測一下,print(TestClass.self == self) 會打印 true 還是 false

請不要停止思考,更有意思的來了😹:
圖片alt

請問,這些 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 是未定義的。
如果使用懶加載的屬性,要注意區分 selfSelf。因為實例已經完成了初始化,此時 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 。在掌握新特性的同時,不定期地去溫習舊的基礎知識,這樣可以有效地保證自己的認知沒有與現實脫節~

以上就是本文的全部內容,如有謬誤,麻煩幫我指出。
如果你也有推薦閱讀的內容,請留言告訴我,大家共同進步!謝謝~ 🤗

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM