也许只有我一个人,但我发现 swift 的某些方面……至少可以说是迟钝。
我大部分时间不使用 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()
}
}
但它仍然要我定义相同的愚蠢初始化程序直到王国来临!
class SomePureViewController : PureViewController {
init(viewModel:ICrackersViewModel) {
super.init()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
现在我明白了这个想法 - 我的子类中没有 init(decoder)
,即使它是在其父类中定义的。
也许我一直在使用 UIViewController
处理这个问题,但之前从未注意到它。
我的问题如下:
- 是否是我做错了什么导致了这种行为?
- 除了继承之外,还有什么方法可以避免重复自己吗?
- 是否有计划改变这一点?
最佳答案
重点是,只要知道基类型就可以初始化一个可能的派生类。
让我们假设一个基类
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 必须保证初始化器让你的对象处于初始化状态,即使它们是从基础对象派生的,所以我想改变它是一件坏事。如果您想定义一个不可反序列化的 UIViewController 并因此违反 LSP,这是您的决定 - 但不要指望语言在这方面支持您。
关于ios - 为什么我必须为我的编程 UIViewController 子类声明相同的必需但未实现的初始化程序(编码器 aDecoder)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31866931/