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

 

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

 

内容概览

  • 前言面试

  • selfSelfswift

  • =====ide

  • 总结函数

 

前言

 

在2014年开源以后,Swift就在飞速地茁壮成长,内涵也愈来愈丰富。post

对于实际使用Swift的人来讲,概念多了就比较容易混淆😨,而后就会致使开发效率低下。毕竟,你须要去查这些概念的正肯定义,或者你须要去写代码进行验证。self, Self, ==, === 就是比较典型的例子。ui

在面试别人的过程当中,我发现有不少朋友分不清楚这些概念。因此,我打算根据我本身的理解来梳理一下这些概念,但愿可以帮你们少走一些弯路。🌟🌟🌟指针

 

selfSelf

 

实例中的 self

首先,最简单的确定是实例中的 self 了:code

图片alt

如上图所示,Xcode 会告诉你这个 self 属于 TestClass 类型。htm

 

类型中的 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 。在掌握新特性的同时,不按期地去温习旧的基础知识,这样能够有效地保证本身的认知没有与现实脱节~

以上就是本文的所有内容,若有谬误,麻烦帮我指出。 若是你也有推荐阅读的内容,请留言告诉我,你们共同进步!谢谢~ 🤗

相关文章
相关标签/搜索