当构建其子类时,Swift泛型超类的初始化程序无法访问

15

我有以下代码:

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' 无法构建,因为它没有可访问的初始化程序

如果我重写init方法:

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

这个代码可以工作,但我不喜欢它。为什么我需要覆盖它,当我不会添加或修改它呢?

我做错了什么吗?

更新:对Nikita Leonov和Icaro的答案进行后续提问

首先是关于所有属性必须具有默认值的规则,我认为我已经满足了这个规则,其中一个可选变量使用nil值作为默认值,不是吗?尽管即使我写var value: T? = nil也不能解决这个问题。

然后从同一文档中“自动初始化程序继承”部分:

如果满足某些条件,则自动继承超类初始化程序

其中一个条件是:

如果您的子类没有定义任何指定初始化程序,则自动继承其超类指定初始化程序。

我认为上面的代码确实符合这个条件。如果我不使用泛型,这实际上是可行的:

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

这个规则是否也适用于泛型类?
4个回答

1
你代码示例的最后一行已经不会再出现编译错误了(自从Swift 3版本)。在Swift 3语言变更中没有提到这一点,因此我只能认为这是一个bug。

0

来自苹果文档

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

您的ilStringProperty类不是基类,因为它继承自ILProperty,所以它必须有一个初始化器。如果您创建一个或覆盖一个都无所谓,因为您的类中至少有一个初始化器,Swift不会免费提供一个。


1
嗯,你说得对。有了这些规则,它应该会继承。它适用于非泛型类,但在泛型类上失败了 - http://swiftstub.com/239455006/真的是一个有趣的案例。我也在苹果开发者论坛上找到了类似的问题,但还没有得到答复 - https://forums.developer.apple.com/thread/5389 - Nikita Leonov
感谢提供相似问题的链接。 - jolen

0

正如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")

-1

这里是苹果文档中的另一段引用:

与 Objective-C 中的子类不同,Swift 子类默认情况下不会继承其超类的初始化程序。Swift 的方法可以防止出现这样一种情况:一个简单的超类初始化程序被一个更专业的子类继承,并用于创建一个未完全或正确初始化的子类新实例。

Apple 的 Swift 编程语言文档 中查看“初始化器继承和重写”部分。

我理解您的沮丧,但 Swift 处理初始化器的方式在概念上更好。


你粘贴的代码后面还有一条注释。 - AntiMoron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接