protocol Car {
var wheels : Int { get set}
init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.wheels = wheels
}
}
wheels = wheels我得到了错误
Error: variable 'self' passed by reference before being initialized
如何在协议扩展中定义初始化程序?
4条答案
按热度按时间6xfqseft1#
正如你所看到的,在这些情况下,这是行不通的,因为在编译时,你必须确保在使用struct/enum/class之前,所有的属性都被初始化了。
您可以将另一个初始值设定项作为要求,以便编译器知道所有属性都已初始化:
从Xcode 7.3 beta 1开始,它可以像预期的那样使用
structs
,但不能使用类,因为如果它们不是final
,协议中的init(wheels: Int)
就是required init
,它可以被覆盖,因此不能通过扩展添加。解决方法(按照编译器的建议):使class
成为final
。另一种解决方法(深入;不含
final class
)要使用类而不使它们成为final,你也可以去掉协议中的
init(wheels: Int)
要求。看起来它的行为和以前没有什么不同,但是考虑一下下面的代码:因此,如果您从泛型上下文中生成一个
Car
,其中您调用init
的类型只被称为Car
,即使在HoverCar
中定义了一个初始化器,也会调用扩展初始化器。这只会发生在协议中没有init(wheels: Int)
要求的情况下。如果你添加它,你会遇到前一个问题,将
class
声明为final
,但现在它打印了两次“HoverCar”。无论哪种方式,第二个问题可能永远不会发生,所以它可能是一个更好的解决方案。旁注:如果我犯了一些错误(代码,语言,语法,...),欢迎您纠正我:)
v2g6jxz62#
我的理解是这是不可能的,因为协议扩展无法知道符合协议的类或结构体具有哪些属性--因此无法保证它们被正确初始化。
如果有办法解决这个问题,我很有兴趣知道!:)
1l5u6lss3#
@Qbyte是正确的。
另外,你可以看看我的Configurable
因为我有
Initable
协议然后为了符合它
我有两种方法,使用
final
或实现init
628mspwn4#
可能不一样,但在我的例子中,我使用了一个静态函数来返回类的对象,而不是使用init。
然后,为了创建对象,我执行了如下操作:
我知道这不是最好的事情,但它是我能找到的最好的解决方案,不耦合业务模型与数据层。
注意:我很懒,我把所有的东西都直接写在了评论里,所以如果有什么不好的地方,让我知道。