self vs Self

学习 swift 语言过程中,会不断发现 swift 一些匪夷所思的语法。学过之后,常常反问一句,真的有必要吗? 没学之前,谁会想到 selfSelf 是不同的。

关键字 self

场景 1 前置 self.

前置 self. 是最常使用的场景,此时关键字 self 同其他语言的 this 关键字类似,可以代表编码过程中当前代码运行所属实例。

class Foo {
    private var name: String = ""
    init(_ name: String) {
        self.name = name //属性名与参数名发生歧义,通过 self. 进行明确指定
    }

    func show() {
        print("name = \(name)") //没有歧义时,直接使用属性名即可
    }
}

需要注意的是,前置 self. 代表的是当前类型的实例对象。在类型定义中,如果前置 self.出现在内嵌类型或匿名函数时,要注意其所指。这点和 es6 简明教程 - 令人崩溃的 this 有些类似。

在 es6 中, 关键字 this, 与函数、对象、类无关,只与执行期上下文有关.

extension Foo {
    //增加一个计算属性 通过匿名函数进行赋值,内部访问 前置 self. 属性
     var age: Int = {
        //print(self.name) //在 swift 5.7 中会直接提示错误 无法找到 self 对象
        return 25
    }()
}

在 swift 5.7 中会直接提示错误 无法找到 self 对象。

场景 2 后置 .self

You can use the postfix self expression to access a type as a value. For example, SomeClass.self returns SomeClass itself, not an instance of SomeClass. And SomeProtocol.self returns SomeProtocol itself, not an instance of a type that conforms to SomeProtocol at runtime.

后置 .self, 返回的是对应的 类型 (type), 而不是 实例 (instance).

最常见到的地方是在对象的反序列化操作中,如:

struct Foo: Codable {
    let name: String
}

let decoder = JSONDecoder()

//返回值就是 Foo 类型实例
let json = """
{
    "name": "Durian"    
}
""".data(using: .utf8)!

//func decode<T>(T.Type, from: Data) -> T 
let foo = try decoder.decode(Foo.self, from: json)

看看 decode 的函数定义,就可以了解到 Foo.self 代表的是 Foo 类型的元类型,

关键字 Self

第一次看见 Self 关键字时,我以为和 self 是一个东西,注意前置和后置就好了。可是,看看上下文,用 Self 的地方根本就不会出现前置后置符号 .

The Self type isn’t a specific type, but rather lets you conveniently refer to the current type without repeating or knowing that type’s name.

In a protocol declaration or a protocol member declaration, the Self type refers to the eventual type that conforms to the protocol.

class Foo {
    private var name: String = ""
    required init(_ name: String) { // 增加 required 关键字
        self.name = name 
    }

    func show() {
        print("name = \(name)") 
    }
}

扩展一个单件属性:

extension Foo {
    static var jay: Self { 
        Self("jay")
    }
}

可见此处 Self 关键字就是类型 Foo 的一种简便的代码写法而已,本身并不会有其他特性。

None None

评论