【问题标题】:swift subclass init tangle快速子类初始化缠结
【发布时间】:2015-08-19 14:29:12
【问题描述】:

我有一个带有两个 init 方法的基类 - 一个是用参数列表指定的,另一个是从 NSDictionary(用于序列化对象)获取参数值的便利 init。一切都很好,直到我尝试创建一个子类 - 如果我尝试调用匹配的 super.init(...) 并要求我调用子类的指定 init,便利 init 会产生错误。超类包含用于提取参数值的密钥,我不想复制代码或拥有公钥值。

我可以设置虚拟值并使用单独的 loadFromDict() 方法(然后可以被覆盖),但这似乎很尴尬。还有其他方法吗?

【问题讨论】:

  • 一个(最小的)代码示例会很有帮助......
  • 您说您不想要“公共”键值。 “内部”键值会起作用吗?如果它们被标记为“内部”,但属于同一模块的一部分,那么大概子类将能够看到它们,并且它们仍然不会公开。如果他们是“私人的”,那当然行不通……

标签: macos swift serialization init


【解决方案1】:

您看到的错误是正常的,好像遵循了 Swift 中的初始化规则。便利 init 必须始终调用同一类中的另一个 init。另一个 init 可能是另一种方便,也可能是指定的。在某些时候,尽管需要在子类中调用指定的 init,然后才能调用超类。 Swift 强制只有指定的 init 才能调用超类 init。这是来自Swift Language reference

为了简化指定和便利之间的关系 初始化器,Swift 应用以下三个规则进行委托 初始化器之间的调用:

规则 1

指定初始化程序必须从其直接超类调用指定初始化程序。

规则 2

便利构造器必须从同一个类中调用另一个构造器。

规则 3

便利构造器最终必须调用指定构造器。

记住这一点的简单方法是:

指定的初始化器必须总是向上委托。

便利初始化器必须始终委托。

【讨论】:

    【解决方案2】:

    the apple docs 的这一部分也可能有帮助:

    假设您为在子类中引入的任何新属性提供默认值,则适用以下两条规则:

    规则 1

    如果您的子类没有定义任何指定的初始化器,它会自动继承其所有超类的指定初始化器。

    规则 2

    如果您的子类提供了其所有超类指定初始化器的实现(通过按照规则 1 继承它们,或者通过提供自定义实现作为其定义的一部分),那么它会自动继承所有超类便利初始化器。

    即使您的子类添加了更多便利初始化程序,这些规则也适用。

    注意

    作为满足规则 2 的一部分,子类可以实现父类指定初始化器作为子类便利初始化器。

    这意味着如果您的子类覆盖了指定初始化程序的所有超类,那么您的子类将继承您希望避免编码两次的便利初始化程序。换句话说,您根本不会尝试在子类中重写便利初始化程序。您只需继承它并按原样使用它。

    下面是它的外观:

    Superclass:              DesignatedInit   ConvenienceInit
                                    |         /
                                (override)   /    // ConvenienceInit
                                    |       /     // will call overridden
                                    |      /      // designated initializer
    Subclass:                DesignatedInit       // in subclass.
    

    【讨论】:

      【解决方案3】:

      最后,我将超类便利 init 设置为指定的 init,并从另一个指定的 init 复制代码,这似乎是从子类调用它的唯一方法。添加可以稍后调用的“设置”方法意味着引入混淆代码的选项。

      为了澄清我的问题,我想将便利 init 子类化,这样我就可以调用 super.init(...) 以及做一些特定于子类的事情。现在将其设置为指定的 init 是微不足道的,但这意味着两个指定的 init 不能共享处理代码,这很不方便。

      我很欣赏 Swift 的 init 设计旨在保护编码人员免于引入错误,但它有时确实感觉有点太不灵活了。

      顺便说一句,我很欣赏这个有用的意图,但发布大量文档并不理想 - 只是一个链接就可以了。

      【讨论】:

        猜你喜欢
        • 2017-10-26
        • 2016-06-30
        • 2023-03-08
        • 2016-05-27
        • 1970-01-01
        • 1970-01-01
        • 2011-01-17
        • 1970-01-01
        • 2020-05-05
        相关资源
        最近更新 更多