覆盖泛型类的初始值设定项

时间:2018-05-15 09:09:42

标签: swift generics initializer

open class CheckItem<T, U: Equatable & CustomStringConvertible>: DataTableItem<T,U,Bool> {
    public override init(_ data: T, getter: @escaping (T) -> U) {
        super.init(data, getter: getter)
    }
}

open class DataTableItem<T, U: Equatable & CustomStringConvertible, V: CustomStringConvertible>: TableItem{
    let data: T
    let getter: (T) -> U

    public init(_ data: T, getter: @escaping (T) -> U) {
        self.data = data
        self.getter = getter
    }
}

open class TableItem: NSObject {
    public var title: String?
}

奇怪的是,不能覆盖子类CheckItem中的init。

编译器抱怨Initializer不会从其超类中覆盖指定的初始值设定项。它抱怨Overriding声明要求“覆盖”&#39;关键字,如果我删除override关键字。

它让我疯狂有人帮忙吗?提前谢谢。

更奇怪的部分是它在LabelItem中起作用

open class LabelItem<T, U: Equatable & CustomStringConvertible, V: CustomStringConvertible>: DataTableItem<T,U,V>{

public override init(_ data: T, getter: @escaping (T) -> U) {
    super.init(data, getter: getter)
}

此处提供完整代码https://github.com/magerate/TableMaker

修改

let checkItem = CheckItem<People, Bool>(people, getter: {(p: People) -> Bool in
        p.isGirl
    })

如果不尝试创建任何CheckItem实例,它会编译。但抱怨

  

无法转换类型&#39;人物&#39;预期的论证类型&#39; Bool&#39;

尝试创建CheckItem的新实例时。

似乎这里的类型推断不正确。

修改

当我将代码部署到swift框架时,它可以正常工作。 WTF

1 个答案:

答案 0 :(得分:0)

我不确定你究竟出了什么问题。当我运行你的代码时,一切似乎都很好。您确定要正确实例化您的实例吗?

let checkItem = CheckItem("Check item data") { (string: String) -> String in
    return string + "checkItem"
}


let labelItem = LabelItem<String, String, Int>("Label item") { (string: String) -> String in
    return string + "labelItem"
}


let dataTableItem = DataTableItem<String, String, Int>("Data table item") { (string: String) -> String in
    return string + "dataTableItem"
}

LabelItemDataTableItem中,您有一个通用的V,它不会在任何地方使用,也不是参数,因此您需要在实例化时明确您的类型,因为您是不在init中传递V类型,编译器无法推断类型。因此<String, String, Int>或满足约束的任何其他类型。

修改

在查看项目代码后(项目没有在我的Xcode上运行,我只将相关代码复制到我的项目中)我仍然没有看到任何问题 - CheckItem的初始化程序都编译:

open class TableItem: NSObject {
    public var title: String?
}

open class DataTableItem<T, U: Equatable & CustomStringConvertible, V: CustomStringConvertible>: TableItem{
    let data: T
    let getter: (T) -> U

    public weak var host: TableItemHost?

    public init(_ data: T, getter: @escaping (T) -> U) {
        self.data = data
        self.getter = getter
    }
}

public protocol TableItemHost: class {}

open class CheckItem<T, U: Equatable & CustomStringConvertible>: DataTableItem<T,U,Bool> {
    public init(_ data: T, host: TableItemHost, getter: @escaping (T) -> U) {
        super.init(data, getter: getter)
        self.host = host
    }

    public override init(_ data: T, getter: @escaping (T) -> U) {
        super.init(data, getter: getter)
    }
}

创建实例:

let checkItem1 = CheckItem("Check item 1 ") { (string: String) -> String in
    return string
}

class Host: TableItemHost {}
let host = Host()
let checkItem2 = CheckItem("Check item 2 ", host: host) { (string: String) -> String in
    return string
}

print(checkItem1.data)
print(checkItem2.data)

将我的代码复制粘贴到游乐场并自行查看。也许除了初始值导致错误之外还有其他内容。

对于测试,您还可以尝试注释掉CheckItem的两个初始值设定项,并使用继承的初始化程序对其进行实例化。这应该有效,因为CheckItem将不再拥有自己的指定初始值设定项(https://stackoverflow.com/a/31459131/1433612