在玩 Swift Playground 时,我注意到除了小写的
self
,还有一个大写的 Self
。它们之间有什么区别吗?如果有,这两个关键字的用法是什么,特别是 Self
的用法?Self
指的是协议中当前“事物”的类型(任何符合协议的内容)。关于其用法的一个示例,请参见Protocol func returning Self。
我找到的有关 Self
的官方文档在协议关联类型声明章节,出乎意料的是,在协议或嵌套类型的章节中没有记录:
self
大体上是 Objective-C 开发者所认为的那样。对于结构体、枚举等的讨论可能是不必要的绕路。 - TommySelf
也可以在类中使用,非常有用。这篇文章介绍了相关内容。
以下是一个示例。你有一个名为MyClass
的类。MyClass
类有返回实例的方法。现在你添加了一个名为MySubclass
的MyClass
子类。你想让这些方法返回MySubclass
的实例而不是MyClass
的实例。下面的代码展示了如何实现。注意这些方法既可以是实例方法也可以是类方法。
class MyClass: CustomStringConvertible {
let text: String
// Use required to ensure subclasses also have this init method
required init(text: String) {
self.text = text
}
class func create() -> Self {
return self.init(text: "Created")
}
func modify() -> Self {
return type(of: self).init(text: "modifid: " + text)
}
var description: String {
return text
}
}
class MySubclass: MyClass {
required init(text: String) {
super.init(text: "MySubclass " + text)
}
}
let myClass = MyClass.create()
let myClassModified = myClass.modify()
let mySubclass = MySubclass.create()
let mySubclassModified = mySubclass.modify()
print(myClass)
print(myClassModified)
print(mySubclass)
print(mySubclassModified)
下一行打印出:// Created
// modifid: Created
// MySubclass Created
// MySubclass modifid: MySubclass Created
在协议和扩展声明中使用Self而不是self
extension protocolName where Self: UIView
{
func someFunction()
{
self.layer.shadowColor = UIColor.red.cgColor
}
}
where
是 Self
的一个很好的例子。 - thedp我认为这个问题需要一个更简单的答案,更侧重于Self
和self
之间的区别,并且可能面向刚接触Swift的人。
self
- 显式引用当前类型或其所在实例的类型。class MyClass {
func showClass() {
print("\(self)")
}
}
let someClass = MyClass()
someClass.showClass()
// prints "MyClass"
Self
- 用于 protocol
和 extension
声明中,特指将符合该协议的最终类型。protocol MyProtocol {
static func returnSelf() -> Self
}
class MyClass: MyProtocol {
// define class
}
MyClass.returnSelf()
// returns MyClass
self
在类型和类型实例中使用,用于引用所在的类型;而Self
在协议和扩展中使用,其中实际的type
尚未知晓。self
;而使用Self
来引用Self
尚不存在的类型。Self
- https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_543|自身self
- https://docs.swift.org/swift-book/ReferenceManual/Expressions.html|自我self - 指代类的实例或对象。
class SampleClassOne {
let name: String
init(name: String) {
self.name = name
}
}
class SampleClassTwo {
static let name: String = "Hello"
private func printName() {
print("\(Self.name)")
}
}
protocol SampleProtocol {
func sampleFunc() -> Self
}
下面是一个简单的例子,让我们一起了解。
extension Int {
var add: Self { //refer to the Type
return self + 100 //refer to the instance
}
}
print(5.add)
struct Person {
static var documentNumner = "9484930"
var name: String
var computedFullName: String {
return ("\(self.name) with document number: \(Self.documentNumner)")
}
}
您不能在静态属性中使用self,但是可以使用Self。
在协议扩展方法体中,Self也可以用作返回类型,它将返回确认类型实例,并用于使用"as"进行类型转换。请参见下面的示例:
extension <Protocol-Name> where Self:<Class-Name> {
static func foo(_ param:Type)-> Self{
guard let abc = method() as? Self else{
return xyz
}
}}
self
和Self
的值有相当多的细微差别 - 我在这个问答中详细讨论了这个问题。 - Hamish