在下面的代码中,我不明白为什么在使用Self()? 如果我用Fireman().
final class Fireman {
var numOfServices = 0
private init(){}
static var shared = Self() <-------- Here !!!
func extinguishFire() {
self.numOfServices += 1
print("Spraying water...\(self.numOfServices)")
}
}
Run Code Online (Sandbox Code Playgroud)
我必须标记该类的另一个原因final是,如果没有该错误消息,我必须包含一个required初始化程序(当我这样做时,我再次收到错误,因为我的初始化程序是private)。所以只是为了避免进一步的子类化,尽管违背我的意愿,我宣布类最终
这与返回 Self 的 Protocol func非常相似,但足够不同,可能值得单独回答。这里有两个问题。
第一个问题是为什么你需要final. 与上面的问题一样,问题在于您做出了编译器无法证明您会遵守的承诺。
考虑以下子类:
class LocalFireman: Fireman {
let zipcode: String
init(zipcode: String) { self.zipcode = zipcode }
}
Run Code Online (Sandbox Code Playgroud)
应该LocalFireman.shared返回什么?它不能返回一个消防员。你说它必须返回 Self(即 LocalFireman)。它不能返回 a LocalFireman,因为它没有要初始化的邮政编码。那么现在怎么办?
Swift 不会让你陷入这个困境,要求你要么确定 的特定类型shared(即它永远是Fireman,即使你在子类上调用它),或者你需要保证不会有子类,或者您需要要求所有子类实现init:
required init() {}
Run Code Online (Sandbox Code Playgroud)
好吧,但你已经做到了。你标记了它final,它仍然抱怨。现在您遇到了编译器限制。重点Self是协方差;它是调用时的动态类型,而不是 context 中的静态类型。这不仅仅是说“我的类型”的一种方便的方式,而且这是一种选择(尽管我认为这可能会改变)。这意味着“我的协变类型”,即使您处于没有任何子类型的情况。
说了这么多,考虑到privateinit,我很困惑为什么你说标记它final是“违背我的意愿”。如果全部init都是私有的,则无论如何都不能对其进行子类化,因此您似乎想要一个最终类,如果是,则只需将类名放在它所在的位置。Self不是为了那个问题(今天)。
这留下了一个问题,即为什么您不能使用所需的 init 来执行此操作。Self作为“类的类型”和Self“符合协议的事物类型”被视为同一事物。所以不能只在课堂情况下思考这个问题;任何东西都可以“继承”(符合)一个协议。所以Self可以潜在地引用一个结构。结构可以是任何大小。因此,允许存储的属性为类型Self会产生内存布局问题。(我也不认为 Swift 承诺类将始终作为指针实现,因此这可能会导致类出现相同的问题,至少在原则上是这样。)
你可以Self从函数返回一个类型的值,但你不能把一个值放在存储属性中(静态和非静态属性都是如此),而且 Swift 也不允许它们用于计算属性(我假设这只是为了一致性)。因此允许以下内容(实际上很有用):
class Fireman {
required init() {}
static func make() -> Self { return Self() }
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么Self。
| 归档时间: |
|
| 查看次数: |
1714 次 |
| 最近记录: |