我班上有两个属性。看到这个可怕的例子:
var length
var doubleLength
如何根据doubleLength
初始化length
?
init() {
self.length = ...
self.doubleLength = self.length * 2
super.init()
}
我收到错误消息,在我致电self
之前无法访问super.init()
。好吧,我需要设置所有变量才能调用super.init()
所以我该怎么办?
答案 0 :(得分:4)
如果self.doubleLength
总是应该是两次self.length
(在这个例子中)你考虑过只使用一个计算属性吗?
class MyClass: MySuperClass {
var length: Double
var doubleLength: Double {
return self.length * 2
}
init(len: Double) {
self.length = len
super.init()
}
}
答案 1 :(得分:1)
您可以暂时延迟doubleLength
隐式解包的可选项的初始化,这将允许临时为nil
分配值并在以后分配它。
class Something: UICollectionViewLayout {
var doubleLength: Int! = nil
var length: Int {
return 50
}
init() {
super.init()
doubleLength = length * 2
}
}
无论如何,在这个特定的情况下,我认为使doubleLength
计算属性更好,因为它总是可以从length
的值计算出来。你的课就像
class Something: UICollectionViewLayout {
var doubleLength: Int {
return length * 2
}
var length: Int {
return 50
}
}
答案 2 :(得分:0)
感谢您的完整复制,即:
import UIKit
class Something: UICollectionViewLayout {
var doubleLength: Int
var length: Int {
return 50
}
init() {
doubleLength = length * 2
super.init()
}
}
通过此我们可以看到您使用吸气剂返还您的财产。我认为这是导致问题的原因。例如,如果你这样做:
import UIKit
class Something: UICollectionViewLayout {
var doubleLength: Int
// Simple variable, no code.
var length = 50
init() {
doubleLength = length * 2
super.init()
}
}
......然后就可以了。
我相信这是因为Swift编译器试图阻止你做任何可能意味着在初始化之前使用基类的方法,属性或变量的事情。在您的示例中,我知道您在技术上不,但请考虑追溯并查看您的初始化程序正在完成的操作有多难。例如,如果您要这样做:
var length: Int {
// Where "width" is a made-up property of UICollectionViewLayout
return width * 3
}
...然后您的代码将从您的初始化程序运行并在调用其自己的init
之前使用UICollectionViewLayout的属性,因此可能使其无效。
所以我最好的猜测是,这是Swift编译器在超级初始化之前全局禁止在子类初始化器之外调用任何代码。
如果你这样做,你会得到完全相同的错误,例如:
class Something: UICollectionViewLayout {
func foo() {
// Do nothing
}
init() {
foo() // error: 'self' used before super.init call
super.init()
}
}
我记得这个被解释的地方是"中级斯威夫特"来自WWDC 2014的视频,来自幻灯片191,大约20分钟,但我也猜测它在书中的某个地方......
答案 3 :(得分:-6)
依赖他人的财产是不好的做法。就像设计数据库时一样,避免计算字段,在设计类时,也可以避免计算字段。您应该使用返回长度* 2的getDoubleLength方法,而不是拥有doubleLength属性。