swift中的self,Self,Class(struct).Type让你头大了嘛?

讲解这一部分,不区分大小写就是耍流氓 ``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)

  1. 是类型(Type),存在于编译器的类型系统中

  2. 逻辑概念,不是内存中的具体实体

  3. 例如:class Dog {}中的 Dog、上述代码中的Self

2、元类型 (Metatype)

  1. 是类型的类型,描述类本身的结构

  2. 在Swift中表示为 SomeClass.Type

  3. 例如:Dog的元类型是 Dog.Type元类型实例 (Metatype Instance)

3、是元类型的具体实例

  1. 存在于运行时内存中

  2. 通过 .self获取,如 Dog.self、Self.self

  3. 本质是一个指向类元数据的指针

最后看个用法

swift 复制代码
let dogType: Dog.Type = Labrador.self //Labrador是我们定义的Dog的子类
func saySomething(dog: Dog.Type) {    
    print("(dog) 汪汪汪!")
}
saySomething(dog: dogType) // Labrador 汪汪汪!

docs.swift.org/swift-book/...

相关推荐
AirDroid_cn2 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
杂雾无尘4 小时前
开发者必看,全面解析应用更新策略,让用户无法拒绝你的应用更新!
ios·xcode·swift
xiangzhihong85 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
Digitally7 小时前
如何将iPhone备份到Mac/MacBook
macos·ios·iphone
帅次8 小时前
【iOS设计模式】深入理解MVC架构 - 重构你的第一个App
ios·swiftui·objective-c·iphone·swift·safari·cocoapods
东坡肘子12 小时前
高温与奇怪的天象 | 肘子的 Swift 周报 #092
人工智能·swiftui·swift
Swift社区13 小时前
Swift 解 LeetCode 320:一行单词有多少种缩写可能?用回溯找全解
开发语言·leetcode·swift
Frank学习路上1 天前
【IOS】XCode创建firstapp并运行(成为IOS开发者)
开发语言·学习·ios·cocoa·xcode
瓜子三百克1 天前
CALayer的异步处理
macos·ios·cocoa
吴Wu涛涛涛涛涛Tao1 天前
一步到位:用 Very Good CLI × Bloc × go_router 打好 Flutter 工程地基
flutter·ios