简体   繁体   English

Swift中的通用约束和初始化程序继承

[英]Generic Constraints and Initializer Inheritance in Swift

I am trying to call an initializer required by protocol A on a type that both conforms to A and is a subclass of C . 我试图在既符合A又是C的子类的类型上调用协议A所需的初始化程序。

All is fine and good if C is a base class. 如果C是基类,那么一切都很好。 But as soon as C subclasses another class, say B , it breaks. 但是,一旦C继承了另一个类,例如B ,它就会中断。

Here's what I am talking about: 这就是我在说的:

protocol A {
    init(foo: String)
}

class B {
    init() {}
}

class C: B {}

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

That works. 这样可行。 But if I change where T: B to where T: C , I get the following error: argument passed to call that takes no arguments . 但是,如果我将where T: Bwhere T: C更改为where T: Cargument passed to call that takes no arguments收到以下错误: argument passed to call that takes no arguments It will only allow me to call B s init . 它只允许我调用B s init

Why can't I call this initializer? 为什么不能叫这个初始化器? I understand that the super class has its own designated initializers that must be called. 我知道超类具有自己必须调用的指定初始化器。 But that will be enforced when someone actually writes the class that subclasses B and conforms to A . 但这将在有人实际编写继承B并符合A的类时强制实施。 (Eg implementing init(Foo: String) and calling super.init(bar: Int) inside). (例如,实现init(Foo: String)并在内部调用super.init(bar: Int) )。

Any help here would be greatly appreciated. 在这里的任何帮助将不胜感激。 Thanks! 谢谢!

Swift provides a default initializer for your base class if it has all properties initialized but not incase of Generics because Swift may think its properties has not been initialized. 如果Swift的所有属性都已初始化,而Swift没有为Generics初始化,则它为基类提供默认的初始化程序,因为Swift可能认为其属性尚未初始化。

So when you constraint your return type as 因此,当您限制返回类型为

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

It requires initialization for class C as Swift cannot provide a default initializer.But if your remove the where clause everything works fine 它需要对C类进行初始化,因为Swift无法提供默认的初始化器。但是,如果删除where子句,则一切正常

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

If you want to return return T(foo: "Hi") : 如果要返回,请return T(foo: "Hi")

You are getting error because class C doesn't have initializer that accepts init(foo: String) 由于类C没有接受init(foo: String)初始化程序,因此出现错误

Change your class C as 将您的C类更改为

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

    }
}

which provides at least one initializer that accepts the argument type. 它提供至少一个接受参数类型的初始化程序。

So, remember if you don't subclass There is already one initializer doing your job and you dont get error. 因此,请记住,如果您没有子类化,那么已经有一个初始化程序可以完成您的工作,并且不会出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM