无法从存储的 属性 初始值设定项引用协变 'Self' 类型
Covariant 'Self' type cannot be referenced from a stored property initializer
在下面的代码中,我不明白为什么在使用 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)")
}
}
另外,我必须标记 class final
的原因是,如果没有它,错误消息是我必须包含一个 required
初始化程序(当我这样做时我再次收到错误消息,因为我的初始化程序是 private
)。所以只是为了避免进一步 subclassing ,尽管违背我的意愿我宣布了 class final
这与 Protocol func returning Self 非常相似,但差异很大,可能值得单独回答。这里有两个问题。
第一个问题是为什么需要 final
。与上述问题一样,问题在于您做出了编译器无法证明您会遵守的承诺。
考虑以下子class:
class LocalFireman: Fireman {
let zipcode: String
init(zipcode: String) { self.zipcode = zipcode }
}
LocalFireman.shared
return应该怎么办?它不能 return 消防员。你说它必须 return 自己(即 LocalFireman)。而且它不能 return a LocalFireman
,因为它没有用于初始化的邮政编码。那么现在呢?
Swift 不会要求您确定 shared
的特定类型(即它始终是 Fireman
,即使您在 subclass 上调用它),或者你需要保证不会有 subclasses,或者你需要要求所有 subclasses 实现 init
:
required init() {}
好的,但你已经说到这里了。你标记它 final
,它仍然抱怨。现在您遇到了编译器限制。 Self
的重点是协方差; it's the dynamic type at the point of calling, not the static type in context。这不仅是 "my type" 的便捷表达方式,而且还是一种选择(尽管我认为这是可以改变的)。这意味着 "my covariant type" 即使您处于不能有任何子类型的情况下。
综上所述,鉴于 private
初始化,我很困惑为什么你说标记它 final
是 "against my will." 如果所有 init
都是私有的,这可以无论如何都不会被 subclassed,所以看起来你想要一个最终的 class,如果是这样,那么只需将 class 名称放在它所在的位置。 Self
不适用于那个问题(今天)。
这留下了一个悬而未决的问题,即为什么您不能使用必需的 init 来执行此操作。 Self
作为 "type of class" 和 Self
作为 "type of thing conforming to a protocol" 被视为同一事物。所以你不能只在 class 的情况下考虑这个;任何东西都可以"inherit"(符合)协议。所以 Self
可以潜在地引用一个结构。结构可以是任何大小。因此,允许存储的 属性 类型为 Self
会产生内存布局问题。 (我也不认为 Swift 承诺 classes 将始终作为指针实现,因此这可能会导致 classes 出现同样的问题,至少在原则上是这样。)
您可以 return 来自函数的类型 Self
的值,但您不能将其放入存储的 属性 中(这对于静态和非静态属性),并且 Swift 也不允许它们用于计算属性(我假设这只是为了保持一致性)。所以以下是允许的(实际上是有用的):
class Fireman {
required init() {}
static func make() -> Self { return Self() }
}
这就是 Self
的目的。
在下面的代码中,我不明白为什么在使用 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)")
}
}
另外,我必须标记 class final
的原因是,如果没有它,错误消息是我必须包含一个 required
初始化程序(当我这样做时我再次收到错误消息,因为我的初始化程序是 private
)。所以只是为了避免进一步 subclassing ,尽管违背我的意愿我宣布了 class final
这与 Protocol func returning Self 非常相似,但差异很大,可能值得单独回答。这里有两个问题。
第一个问题是为什么需要 final
。与上述问题一样,问题在于您做出了编译器无法证明您会遵守的承诺。
考虑以下子class:
class LocalFireman: Fireman {
let zipcode: String
init(zipcode: String) { self.zipcode = zipcode }
}
LocalFireman.shared
return应该怎么办?它不能 return 消防员。你说它必须 return 自己(即 LocalFireman)。而且它不能 return a LocalFireman
,因为它没有用于初始化的邮政编码。那么现在呢?
Swift 不会要求您确定 shared
的特定类型(即它始终是 Fireman
,即使您在 subclass 上调用它),或者你需要保证不会有 subclasses,或者你需要要求所有 subclasses 实现 init
:
required init() {}
好的,但你已经说到这里了。你标记它 final
,它仍然抱怨。现在您遇到了编译器限制。 Self
的重点是协方差; it's the dynamic type at the point of calling, not the static type in context。这不仅是 "my type" 的便捷表达方式,而且还是一种选择(尽管我认为这是可以改变的)。这意味着 "my covariant type" 即使您处于不能有任何子类型的情况下。
综上所述,鉴于 private
初始化,我很困惑为什么你说标记它 final
是 "against my will." 如果所有 init
都是私有的,这可以无论如何都不会被 subclassed,所以看起来你想要一个最终的 class,如果是这样,那么只需将 class 名称放在它所在的位置。 Self
不适用于那个问题(今天)。
这留下了一个悬而未决的问题,即为什么您不能使用必需的 init 来执行此操作。 Self
作为 "type of class" 和 Self
作为 "type of thing conforming to a protocol" 被视为同一事物。所以你不能只在 class 的情况下考虑这个;任何东西都可以"inherit"(符合)协议。所以 Self
可以潜在地引用一个结构。结构可以是任何大小。因此,允许存储的 属性 类型为 Self
会产生内存布局问题。 (我也不认为 Swift 承诺 classes 将始终作为指针实现,因此这可能会导致 classes 出现同样的问题,至少在原则上是这样。)
您可以 return 来自函数的类型 Self
的值,但您不能将其放入存储的 属性 中(这对于静态和非静态属性),并且 Swift 也不允许它们用于计算属性(我假设这只是为了保持一致性)。所以以下是允许的(实际上是有用的):
class Fireman {
required init() {}
static func make() -> Self { return Self() }
}
这就是 Self
的目的。