Swift 关键词系列 ——— self / Self

3,862 阅读3分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战」。

在 Swift 中,self通常是指类或结构中的当前对象,Self表示任何当前类型。

self

self是Swift 中最简单和最常见的。它后面通常跟一个.和一个属性或函数名称。如

self.name = "Joke" 
self.test()

self是该类中的类(或结构)对当前对象(“实例”)的引用。

显式的self

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .red
    }
}

viewDidLoad()方法中,我们使用了self关键字。所以我们使用self.view来指代属性。通过使用显式的self可以消除对您所指内容的产生任何混淆。

隐式的self

但在 Swift 中, 我们经常习惯不去使用self,这个就是隐式的。(不写不代表不存在😁)。如下面我们经常写的一个控制器:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
    }
}

为什么可以用隐式的self呢?那是因为对的当前对象的引用,我们可以使用是隐式的self。如果我们使用的是隐式的self,Swift就知道我们指的是当前对象的属性,它通过做出这个假设为我们节省编码时间。

什么时候使用显式的“self”?

  • 如果您正在处理一个属性,并且存在命名冲突,那么您使用self.明确告诉 Swift 您指的是当前对象的该属性。
var  num = 0
class ViewController: UIViewController {
    var num = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        self.num = 0
    }
}

或者

class IccClass {
    var name: String = "class prop"
    func setProperty(name:String = "method attribute") -> () {
        print(self.name) // Output: class property
        print(name) // Output: method attribute
    }

}

我们需要注意上面的俩个name代表的是不同的意思。这个时候使用self,就不会用类属性与局部变量混淆。

  • 在闭包中设置时必须使用self.,使闭包中的捕获语义清晰
DispatchQueue.main.async {
    self.someFunc(view: self.view)
}

一个经验法则是:你可以平时写隐式的self,当你需要明示或者冲突的时候就必须使用self

例如,解决命名冲突或使闭包中的捕获语义清晰。您可以在代码中添加所有属性self.,但这并不能让它变得更清晰。

更多的必须实现显式的self的情况,请在留言区让我学习😁。

Self

在 Swift 中,Self指的是一种类型——通常是当前上下文中的当前类型。正如小写self可以表示当前对象,大写Self可以表示当前类型。

  • 在协议中,它是指在任何特定用途中符合协议的类型。
extension Numeric {
    func squared() -> Self {
        return self * self
    }
}

2.squared() 
2.0.squared() 

在此上下文中,Self指的是符合Numeric协议的类型。在示例中2去调用则Self将是具体类型Int。如果是2.0则Self将是具体类型Double

如果要限制具体类型则在extension使用Self配合我们之前说的where

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
extension UILabel {
    func makeForTitle() -> Self {
        self.font = .boldSystemFont(ofSize: 24)
        self.textColor = .darkGray
        self.adjustsFontSizeToFitWidth = true
        self.minimumScaleFactor = 0.75
        return self
    }
}

UILabel().makeForTitle()//可以链式调用....