【问题标题】:Swift generic superclass' init not accessible when constructing its subclassSwift 泛型超类的 init 在构造其子类时无法访问
【发布时间】:2015-09-11 10:50:32
【问题描述】:

我有以下代码:

class ILProperty<T> {
    var value: T?
    init(_ value: T) {
        self.value = value
    }
}

typealias ILStringProperty = ilStringProperty<String>
class ilStringProperty<String>: ILProperty<String> {
}

let x = ILStringProperty("X")

最后一行是编译错误:

'ILStringProperty' 无法构造,因为它没有可访问的初始化程序

如果我覆盖初始化:

override init(_ value: String) {
    super.init(value)
}

会起作用,但我不喜欢它。为什么我不会添加/修改它时需要覆盖它?

我做错了吗?

更新:跟进 Nikita Leonov 和 Icaro 的回答问题

首先,关于所有属性都必须有默认值,我认为我确实满足了这条规则,其中可选 var 默认为 nil 值,不是吗?虽然即使我写var value: T? = nil 也不能解决它。

然后从同一 documentation 部分“自动初始化器继承”:

如果满足某些条件,则会自动继承超类初始值设定项

一个条件是:

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

我认为上面的代码确实满足了。如果我不使用泛型,这实际上会起作用:

class ILProperty {
    var value: Any?
    init(_ value: Any) {
        self.value = value
    }
}
class ILStringProperty: ILProperty {
}
let x = ILStringProperty("X")

这条规则也应该适用于泛型类吗?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    代码示例中的最后一行不再给出编译错误(从 Swift 3 开始)。 Swift 3 Language Changes 中没有提到这一点,所以我只能假设这是一个错误。

    【讨论】:

      【解决方案2】:

      来自apple documentation

      Swift 为任何结构或基类提供默认初始化器 它为其所有属性提供默认值,但不提供 提供至少一个初始化程序本身。默认初始化器 只需创建一个新实例,并将其所有属性设置为 默认值。

      您的类 ilStringProperty 不是基类,因为它继承自 ILProperty,因此它必须有一个初始化程序,如果您创建一个或覆盖一个并不重要,因为您的类中至少有一个初始化程序,因为 swift 不会提供一个免费。

      【讨论】:

      • 嗯。你说的对。考虑到这个规则,它应该继承。它适用于非泛型类,但在泛型类上失败 - swiftstub.com/239455006 非常有趣的案例。我也在 Apple 开发者论坛上发现了类似的问题,但还没有答案——forums.developer.apple.com/thread/5389
      • 感谢类似问题的链接
      【解决方案3】:

      正如ganzogo 提到的,它似乎在最新的 Swift (3.0) 上运行良好。另外,为什么要声明一个单独的类来分配给typealias?我已经在 Playground 中尝试过,看起来还可以:

      class ILProperty<T> {
          var value: T?
          init(_ value: T) {
              self.value = value
          }
      }
      
      typealias ILStringProperty = ILProperty<String>
      let x = ILStringProperty("X")
      

      【讨论】:

        【解决方案4】:

        这是 Apple 文档中的另一个引述

        与 Objective-C 中的子类不同,Swift 子类不继承 默认情况下,它们的超类初始值设定项。 Swift 的方法可以防止 继承超类的简单初始化程序的情况 由一个更专业的子类来创建一个新的实例 未完全或正确初始化的子类。

        Swift Programming Language document from apple 中查看“Initializer Inheritance and Overriding”部分。

        我不理解你的沮丧,但 Swift 处理初始化程序的方式在概念上更好。

        【讨论】:

        • 在您粘贴的阶段之后还有一个注释。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-24
        • 2019-02-20
        相关资源
        最近更新 更多