我有一个带有两个init方法的基类 - 一个用参数列表指定,另一个是从NSDictionary(用于序列化对象)获取参数值的便捷init。一切都很好,直到我尝试创建一个子类 - 如果我尝试调用匹配的super.init(...)并要求我调用子类的指定init,则easy init会产生错误。超类包含用于提取参数值的键,我不想复制代码或具有公钥值。
我可以设置虚拟值并使用单独的loadFromDict()方法(然后可以覆盖它),但这看起来很尴尬。还有另一种方式吗?
答案 0 :(得分:0)
您看到的错误是正常的,就像遵循Swift中的初始化规则一样。一个方便的init必须始终在同一个类中调用另一个init。另一个init可能是另一个方便,或者它可以是指定的。在某些时候,虽然在调用超类之前需要在子类中调用指定的init。 Swift强制只有指定的init才能调用超类init。这来自Swift Language reference
简化指定与便利之间的关系 初始化程序,Swift应用以下三个委托规则 初始化程序之间的调用:
规则1
指定的初始值设定项必须从其直接超类中调用指定的初始值设定项。
规则2
便捷初始化程序必须从同一个类调用另一个初始值设定项。
规则3
便捷初始化程序必须最终调用指定的初始化程序。
记住这一点的一个简单方法是:
指定的初始值设定项必须始终委派。
便利初始化程序必须始终委派。
答案 1 :(得分:0)
这部分the apple docs也可能有所帮助:
假设您为在子类中引入的任何新属性提供默认值,则适用以下两个规则:
规则1
如果您的子类没有定义任何指定的初始值设定项,它会自动继承其所有超类指定的初始值设定项。
规则2
如果您的子类提供了所有超类指定初始化器的实现 - 通过按照规则1继承它们,或者通过提供自定义实现作为其定义的一部分 - 那么它会自动继承所有超类便捷初始化器。 / p>
即使您的子类添加了更多便利初始值设定项,这些规则也适用。
请注意
子类可以将超类指定的初始化程序实现为子类便捷初始化程序,作为满足规则2的一部分。
这意味着如果您的子类重写超级类指定初始值设定项的所有,那么您的子类将继承您希望避免编码两次的便捷初始值设定项。换句话说,您根本不会尝试在子类中重写便捷初始化程序。你只需继承它并按原样使用它。
以下是它的外观:
Superclass: DesignatedInit ConvenienceInit
| /
(override) / // ConvenienceInit
| / // will call overridden
| / // designated initializer
Subclass: DesignatedInit // in subclass.
答案 2 :(得分:0)
最后,我将超类便捷init设置为指定的并从其他指定的init复制了代码,这似乎是从子类调用它的唯一方法。添加一个可以在以后调用的'setup'方法意味着引入混淆代码的选项。
为了澄清我的问题,我想将便利init子类化,这样我就可以调用super.init(...)以及做一些特定于子类的东西。这使得它成为一个指定的初始化是微不足道的,但这意味着两个指定的inits不能共享处理代码,这是不方便的。
我很欣赏Swift init设计旨在保护程序员不会引入错误,但有时它确实感觉有点太不灵活。
顺便说一下,我很欣赏这个有用的意图,但发布大量的文档并不理想 - 只是链接没问题。