Swift self, Self, ==, === 傻傻分不清楚?
本文首发于 Ficow Shen's Blog,原文地址: Swift self, Self, ==, === 傻傻分不清楚?。
内容概览
前言
self
和Self
==
和===
总结
前言
在2014年开源之后,Swift就在飞速地茁壮成长,内涵也越来越丰富。
对于实际使用Swift的人来说,概念多了就比较容易混淆,然后就会导致开发效率低下。毕竟,你需要去查这些概念的正确定义,或者你需要去写代码进行验证。self, Self, ==, === 就是比较典型的例子。
在面试别人的过程中,我发现有很多朋友分不清楚这些概念。所以,我打算根据我自己的理解来梳理一下这些概念,希望能够帮大家少走一些弯路。
self
和 Self
实例中的 self
首先,最简单的肯定是实例中的 self
了:
如上图所示,Xcode 会告诉你这个 self
属于 TestClass
类型。
类型中的 self
:
如上图所示,Xcode 会告诉你这个 self
是 TestClass.Type
类型。稍等一下,.Type
是什么东西?
从字面意思去理解,这个 self
是 TestClass
这个类型本身。
如果为该类型定义一个静态常量(static let
),我们就可以在类型的静态方法(static func
)中去访问这个静态常量。因为,它们都属于这个类型本身。self.classLet
也就是在访问 TestClass
这个类型本身的常量 classLet
。
实体类型(concrete type)中的 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
。在掌握新特性的同时,不定期地去温习旧的基础知识,这样可以有效地保证自己的认知没有与现实脱节~
以上就是本文的全部内容,如有谬误,麻烦帮我指出。
如果你也有推荐阅读的内容,请留言告诉我,大家共同进步!谢谢~
Swift self, Self, ==, === 傻傻分不清楚?的更多相关文章
- JS魔法堂:属性、特性,傻傻分不清楚
一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...
- MVP MVC MVVM 傻傻分不清
最近MVC (Model-View-Controller) 和MVVM (Model-View-ViewModel) 在微软圈成为显学,ASP.NET MVC 和WPF 的Prism (MVVM Fr ...
- Java:接口和抽象类,傻傻分不清楚?
01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...
- [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!
十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...
- OCA,OCP,OCM傻傻分不清?
可能大家知道OCA.OCP.OCM的关系是一个比一个难考,一个比一个含金量高,但是你知道具体的考试科目.考试方式.就业形势区别吗?不知道的话这篇通俗易懂的文章会让你一目了然. 区别一:含金量 ■OCA ...
- 学点经济学:M0、M1、M2、M3,傻傻分不清?(转载)
来源:http://t.10jqka.com.cn/pid_97006727.shtml 学点经济学:M0.M1.M2.M3,傻傻分不清? 25,508人浏览 2018-08-03 11:06 常听人 ...
- 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】
文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...
- 傻傻分不清之 Cookie、Session、Token、JWT
傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...
- Shell中傻傻分不清楚的TOP3
Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...
- ASCII、Unicode、UTF-8、UTF-8(without BOM)、UTF-16、UTF-32傻傻分不清
ASCII.Unicode.UTF-8.UTF-8(without BOM).UTF-16.UTF-32傻傻分不清 目录 ASCII.Unicode.UTF-8.UTF-8(without BOM). ...
随机推荐
- 思维分析逻辑 4 DAY
目录 竞品分析 波特五力模型 竞品分析步骤 分析目的 对比分析 初步结论 活动营销分析 用户增长分析 用户增长基本模型 渠道思维(前期) 用户思维(中期) ROI思维(后期) 增长思维 北极星指标:一 ...
- 数据抽取平台pydatax介绍
缘起一: 公司现有数据仓库,是通过kettle从mysql抽取到目标库,运行多年,主要有以下问题, 1,效率低:kettle抽取行数少 2,容错性差:一个表抽取出错就导致后续计算 ...
- Java Base64编码使用介绍
Base64编码介绍 BASE64 编码是一种常用的字符编码,Base64编码本质上是一种将二进制数据转成文本数据的方案. 但base64不是安全领域下的加密解密算法.能起到安全作用的效果很差 ...
- Oracle 12c中增强的PL/SQL功能
英文链接:http://www.oracle.com/technetwork/issue-archive/2013/13-sep/o53plsql-1999801.html Oracle 12c增强了 ...
- re.sub参数之回调函数
from calendar import month_abbr import re def change_date(m): mon_name = month_abbr[int(m.group(1))] ...
- 在Ubuntu搭建DHCP服务器
一.提供DHCP的服务器,自己必须有固定的IP地址 不然局域网就乱了,服务器自身启动(比如搭建完DHCP服务后,重新启动了服务器)的时候,DHCP服务器没有IP地址,无法和自己的DHCP服务通信. 在 ...
- Gitlab的部署
# Gitlab sudo docker run --detach \ --hostname gitlab.example.com \ --publish 443:443 --publish ...
- 【Azure 应用服务】App Service for Container中配置与ACR(Azure Container Registry)的RABC权限
问题描述 在使用App Service for container时,在从ACR(Azure Container Registry)中获取应用的镜像时,需要使用对应的权限.默认情况为在ACR中启用Ad ...
- 【Azure API 管理】APIM不能连接到 App Service (APIM cannot connect to APP service)
问题描述 APIM 无法正确连接到App Service,返回500错误: { "statusCode": 500, "message": "Inte ...
- 【Azure 环境】台湾同胞:詢問大陸所有廠牌手機是否都可透過通知中心發送訊息
什么是 Azure 通知中心? Azure 通知中心提供易于使用且向外扩展的推送引擎,可用于将通知发送到任何平台 (iOS.Android.Windows.Kindle.百度等 ) 从任何后端 (云和 ...