class Person { var name: String // 堆代码 duidaima.com init(name: String) { // 这里的 self.name 指的是实例属性 // 而 name 是传入的参数 self.name = name } func introduce() { print("大家好,我叫 \(self.name)") // 其实这里的 self 可以省略 print("大家好,我叫 \(name)") } } let xiaoming = Person(name: "小明") xiaoming.introduce()什么时候必须用 self 呢?主要是这两种情况:
struct Point { var x: Double var y: Double mutating func move(x: Double, y: Double) { // 必须用 self 来区分属性和参数 self.x += x self.y += y } }2. 在闭包中引用实例属性时
class ViewController { var count = 0 func setupTimer() { Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in // 闭包中必须显式使用 self self.count += 1 print("计数: \(self.count)") } } }Self:类型的占位符
protocol Duplicatable { // Self 表示遵循协议的具体类型 func duplicate() -> Self } class Document: Duplicatable { var content: String init(content: String) { self.content = content } // 这里返回的是 Document 类型 func duplicate() -> Self { // 需要用 type(of:) 来创建相同类型的实例 return type(of: self).init(content: self.content) } requiredinit(content: String) { self.content = content } }Self 的妙处在于它的多态性。不同的类型遵循同一个协议时,Self 会自动变成对应地类型:
class PDFDocument: Document { // duplicate() 返回的是 PDFDocument,不是 Document } class WordDocument: Document { // duplicate() 返回的是 WordDocument,不是 Document }Self.self:类型的元类型
protocol Registrable { staticfunc register() } extension Registrable { staticfunc register() { // Self.self 获取的是具体类型的元类型 print("正在注册 \(Self.self)") } } class UserService: Registrable {} class PaymentService: Registrable {} // 调用静态方法 UserService.register() // 打印: 正在注册 UserService PaymentService.register() // 打印: 正在注册 PaymentService在实际开发中,Self.self 经常用在需要传递类型信息的场景:
// 泛型函数,需要知道具体类型 func createInstance<T: Decodable>(of type: T.Type, from json: String) -> T? { // 使用传入的类型信息来解码 JSON let data = json.data(using: .utf8)! returntry? JSONDecoder().decode(type, from: data) } // 在协议扩展中使用 protocol JSONDecodable: Decodable { staticfunc decode(from json: String) -> Self? } extension JSONDecodable { staticfunc decode(from json: String) -> Self? { // 这里的 Self.self 就是调用者的具体类型 return createInstance(of: Self.self, from: json) } }实战技巧:什么时候用哪个?
.需要把类型作为参数传递
class Animal { // ❌ 错误:class 中不能直接返回 Self // func clone() -> Self { ... } // ✅ 正确:需要用 required init func clone() -> Self { return type(of: self).init() } required init() {} }2. 忘记 weak self
class ViewController { func loadData() { APIClient.request { data in // ❌ 可能造成循环引用 self.updateUI(with: data) // ✅ 使用 weak self // [weak self] in // self?.updateUI(with: data) } } }3. Self 和具体类型名混用
protocol Comparable { // ❌ 不够灵活 func isEqual(to other: MyClass) -> Bool // ✅ 使用 Self 更通用 func isEqual(to other: Self) -> Bool }