也许这只是我,但我发现迅速的某些方面......至少可以说是钝的。
我大部分时间都不使用Interface Builder,因为我喜欢使用PureLayout
。所以我希望创建一个UIViewController
子类,比如PureViewController
,它有一个方便的init
没有参数:
class PureViewController : UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
}
但这并不合适,因为XCode告诉我,我还必须实现init(coder aDecoder: NSCoder)
。好的,没关系!这就是我创建这个类的原因 - 所以我不必再为子类做这个。
class PureViewController : UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
好的,现在这就是我没有得到的。
我使用初始化程序SomePureViewController : PureViewController
...
init(viewModel:ICrackersViewModel)
class SomePureViewController : PureViewController {
init(viewModel:ICrackersViewModel) {
super.init()
}
}
但 STILL 希望我定义同样的愚蠢初始化程序,直到王国来临!
class SomePureViewController : PureViewController {
init(viewModel:ICrackersViewModel) {
super.init()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
现在我理解了这个想法 - 我的子类中没有init(decoder)
,即使它是在其父类中定义的。
也许我总是用UIViewController
处理这个问题,之前从未注意过。
我的问题如下:
答案 0 :(得分:2)
关键是可以通过了解基类型来初始化可能派生的类。
让我们假设一个基类
class Base {
let value: Int
required init(value: Int) {
self.value = value
}
}
和一个功能
func instantiateWith5(cls: Base.Type) -> Base {
return cls.init(value: 5)
}
然后我们可以做
let object = instantiateWith5(Base.self)
现在,如果有人定义派生类
class Derived: Base {
let otherValue: Int
init() {
otherValue = 1
super.init(value: 1)
}
required init(value: Int) {
fatalError("init(value:) has not been implemented")
}
}
我们至少可以致电
let object2 = instantiateWith5(Derived.self)
违反了LSP,但这是你的代码问题,而不是语言。
Swift必须保证初始化器将对象保持在初始化状态,即使它们是从基础对象派生的,所以我想改变它会是一件坏事。如果您想定义一个不可反序列化并因此违反LSP的UIViewController,那么这是您的决定 - 但不要指望该语言在此支持您。
答案 1 :(得分:1)
我认为这是一个很快的问题,如何避免这种情况。我们都讨厌这个空的致命错误初始化器。
答案 2 :(得分:1)
由于初始化程序标有required
关键字,因此所有子类都必须实现该初始化程序,并且还必须在其实现上指定required
,以便其子类也是必需的实现它。
必需的初始化程序
在之前写下所需的修饰符 类初始值设定项的定义,用于指示每个子类 该类必须实现该初始化程序
您还必须在所需初始化程序的每个子类实现之前编写必需的修饰符,以指示初始化程序要求适用于链中的其他子类。“
自1.0以来,它一直是Swift语言的一部分,不太可能改变。
问题实际上与在UIViewController类定义中使用required
关键字有关。理论上这可以改变,但我认为这不太可能。