讲解这一部分,不区分大小写就是耍流氓 ``self(首字母小写)``self
是Swift 中最简单和最常见的。它后面通常跟一个.
和一个属性或函数名称。
ini
self.name = "Joke"
self.test()
self是类(或结构体)中对当前对象也就是"实例"的引用 接下来看下在类方法或者说静态方法中小写self是什么
Swift 中的元类型用 .Type 表示。比如 Int.Type 就是 Int 的元类型。类型与值有着不同的形式,就像 Int 与 5 的关系。元类型也是类似,.Type 是类型,类型的 .self 是元类型的值。例如可以像下边这样定义
swift
let intMetatype: Int.Type = Int.self
Self(首字母大写)
在 Swift 中,Self
指的是一种类型------通常是当前上下文中的当前类型。正如小写self
可以表示当前对象,大写Self
可以表示当前类型。在定义协议的时候Self 用的频率很高
在协议中,它是指在任何特定用途中符合该协议的类型。
swift
extension Numeric {
func squared() -> Self {
return self * self
}
}
2.squared() //这里的2是整数
2.0.squared() //这里的2.0是double
在此上下文中,Self
指的是符合Numeric
协议的类型。在示例中2去调用则Self
将是具体类型Int
。如果是2.0则Self
将是具体类型Double
如果要限制具体类型则在extension
使用Self
配合我们之前说的where
。
sql
extension Numeric where Self == Int {
func squared() -> Self {
return self * self
}
}
2.squared()
2.0.squared() //Referencing instance method 'squared()' on 'Numeric' requires the types 'Double' and 'Int' be equivalent
从上边的例子也可以看出,在静态方法或者对象方法中,都可以作为返回类型。表示返回类型是方法所在的类的类型,而不是方法声明所在的类的类型。它类似于 OC 中的instancetype
。
swift
class Base {
// 返回类型是 Base
func create() -> Base {
return Base()
}
// 返回类型是 Self
func createSelf() -> Self {
return self
}
}
class Subclass: Base {
// 返回类型是 Subclass
override func create() -> Base {
return Subclass()
}
// 返回类型是 Subclass
override func createSelf() -> Self {
return self
}
}
可以说Self就是为继承和协议而生的,我们来看下边的错误
swift
class Cat {
var age : Int = 0
func meow(){
print("(self) 喵喵喵!")
}
func makeNewCat() -> Self{
return Cat()//Cannot convert return expression of type 'Cat' to return type 'Self'
return self //正确
}
}
这个错误是因为 Self 类型需要返回实际的当前类型实例,而不是基类 Cat 的实例。这里有点难理解,想象Cat被继承后,在子类对象上调用makeNewCat,返回值类型为Self,也就是子类,但是实际返回的是Cat,这个冲突就是这里报错的关键而且即便当前方法是static的,也会有相同的错误提示,可见同是否为类方法没有关系,而是与Self本身的设计相关咱再看另外一个问题
scss
func meow() -> type(of: self) { //报错:Cannot find type 'type' in scope
print("(self) 喵喵喵!")
type(of: self)
return Cat()
}
这个错误是因为Swift 是静态类型语言,函数的返回类型必须在编译时明确指定,而 type(of:) 的返回值是运行时动态确定的(取决于传入的实例),编译时无法预知其具体类型。另外还有更重要的原因:
swift
public func type<T, Metatype>(of value: T) -> Metatype
这个type(of: )方法返回的是元类型,但函数声明需要具体的类型名称类方法中的self 和 大写的Self 以及类.self什么关系?
c语言中一个类型标明了其对象存储需要的内存大小等信息因此所有的值都应该有一个类型,而静态属性和类方法存在于某class上,所以在这种情况下,某class.self 就拥有了一种类型:Self.Type。比如:Dog.Type 就保存所有 Dog 的类型值。这里可能有点别扭,我们平时说的某class其实是一个对象,如果要获取这个对象需要用某class.self来获取首先看下类方法中的self和Dog.self的关系
swift
class Dog {
class func bark() {
print("(self) 汪汪汪!")
}
func instanceBark(){
if Dog.self == Self.self{
print("(Self.self) 汪汪汪!")
}
}
}
在类方法中打一个断点,注意打印的时候用p,而不是po,po 打印出来都是sort.Dog,也就是类对象本身
less
p self
(@thick sort.Dog.Type) @thick sort.Dog.Type
p Dog.self
(sort.Dog.Type) sort.Dog.Type
可见类方法中的self和Dog.self是同一种对象,其实它们是同一个对象,也就是Dog这个类自身(好难说清楚,如果你读完本文很困惑,可以私信我)可能至此你觉得"我懂了",但是请看这个:

self.name 类的属性可以取到nnn没什么问题但是为什么Self.name也可以取到?看这个打印结果貌似self 和Self相同呀,但是怎么解释下边这个呢?

Self在这里等同于Dog,我们的self是Dog对应的类对象,注意这里类对象和类的关系,因此应该用Self.self 和self比较(这里真的很绕)
关键概念区分
1、类 (Class)
-
是类型(Type),存在于编译器的类型系统中
-
逻辑概念,不是内存中的具体实体
-
例如:class Dog {}中的 Dog、上述代码中的Self
2、元类型 (Metatype)
-
是类型的类型,描述类本身的结构
-
在Swift中表示为 SomeClass.Type
-
例如:Dog的元类型是 Dog.Type元类型实例 (Metatype Instance)
3、是元类型的具体实例
-
存在于运行时内存中
-
通过 .self获取,如 Dog.self、Self.self
-
本质是一个指向类元数据的指针
最后看个用法
swift
let dogType: Dog.Type = Labrador.self //Labrador是我们定义的Dog的子类
func saySomething(dog: Dog.Type) {
print("(dog) 汪汪汪!")
}
saySomething(dog: dogType) // Labrador 汪汪汪!