Swift

时间:2016-10-30 23:19:11

标签: swift generics swift3 swift-protocols

我正在尝试调用协议A所需的初始值设定项,该类型符合A并且是C的子类。

如果C是基类,那么一切都很好。但是,只要C将另一个类子类化,比如B,它就会中断。

这就是我在谈论的内容:

protocol A {
    init(foo: String)
}

class B {
    init() {}
}

class C: B {}

func makeSomething<T: A>() -> T where T: B {
    return T(foo: "Hi")
}

有效。但是,如果我将where T: B更改为where T: C,则会收到以下错误:argument passed to call that takes no arguments。它只允许我拨打B s init

为什么我不能称之为初始化程序?我知道超类有自己的指定初始值设定项,必须调用。但是当有人实际编写子类B并符合A的类时,这将被强制执行。 (例如,实施init(Foo: String)并在其中调用super.init(bar: Int)

这里的任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

Swift为你的基类提供了一个默认初始值设定项,如果它已经初始化了所有属性但不包含泛型,因为Swift可能认为它的属性尚未初始化。

因此,当您将返回类型约束为

func makeSomething<T: A>() -> T where T: C

它需要为C类初始化,因为Swift无法提供默认的初始化器。但是如果你删除where子句一切正常

func makeSomething<T: A>() -> T {
    return T(foo:"string")
}

如果您想返回return T(foo: "Hi")

您收到错误,因为C类没有接受init(foo: String)

的初始值设定项

将您的C班改为

class C: A {
    required init(foo: String) {

    }
}

提供至少一个接受参数类型的初始值设定项。

所以,请记住,如果你没有子类已经有一个初始化程序正在完成你的工作并且你没有得到错误。