我正在尝试构建一组共享通用初始化代码的类。除了继承之外,我认为协议是必经之路。虽然协议和协议扩展适用于实例和静态方法,但在使其与初始化程序一起使用时遇到了一些麻烦。
假设我们有此协议:
protocol CloudServiceWrapper {
static var isConfigured: Bool { get }
init()
func initialize()
}
现在,我们要在协议扩展中为isConfigured
和init()
添加默认实现:
extension CloudServiceWrapper {
static var isConfigured: Bool {
get {
return true
}
}
init() {
print("Initializing generic CloudServiceWrapper")
self.init()
if Self.isConfigured {
initialize()
}
}
}
最后,让我们创建一个类来实现此协议并尝试从其默认实现中受益:
class OneDriveWrapper: CloudServiceWrapper {
required init() {
// CloudServiceWrapper() // error: protocol type 'CloudServiceWrapper' cannot be instantiated
// self = CloudServiceWrapper.init() // error: cannot assign to value: 'self' is immutable
// super.init() // error: 'super' members cannot be referenced in a root class
// (self as CloudServiceWrapper).init() // error: static member 'init' cannot be used on instance of type 'CloudServiceWrapper'
print("Initializing OneDriveWrapper")
}
func initialize() {
print("Done")
}
}
当尝试构建OneDriveWrapper
类的新实例时,我简直找不到办法调用该类的初始化程序和默认协议实现。并且不可能在init()
类中省略OneDriveWrapper
,因为根据协议定义它是必需的,并且似乎不被认为是协议扩展的“实现”。
实际上,更广泛地说,即使我知道实例方法是可行的,我也找不到显式调用协议扩展的初始化程序的任何方法。
我在做什么错?您知道结合类的初始化程序和协议扩展的初始化程序的任何方法吗?我应该回到类继承而不是协议和扩展上吗?
谢谢!
答案 0 :(得分:3)
init
中的protocol
是required
,因此必须明确实现,即无法使用默认实现。
对于“显式调用协议扩展的初始化程序”,您无法实例化协议类型。
我建议为此使用继承。
答案 1 :(得分:2)
Public default init in protocol是一个类似的问题。
尽管协议提供了默认实现,为什么类仍需要具有init?答案是,它没有提供默认的实现,而只是提供了另一个init,这就要求这里存在类init()
。
由于不确定您的协议是否涵盖使用该协议的类的所有成员,因此您在协议中声明的任何初始化器都需要将类的“未知”成员的初始化委托给该类提供的另一个初始化器本身。 Source
您的协议初始化可能会被“ init()
”类所遮盖,因此您将无法使用它。可能在类初始化程序/协议的必需初始化程序中添加参数,或者在协议扩展名ìnit()
中添加参数。如果该类没有覆盖协议扩展的初始化,则可以使用它来初始化该类。
初始化是必需的,因为可以对类进行子类化,并且不必继承初始化程序,请参见inheritance doc和initialization doc under Initializer Inheritance and Overriding。如果不需要初始化,则子类将不再遵守该协议,这是不可取的,因此协议中设置的初始化仅由所需的初始化程序填充。
注意:在required init()
中,您尝试调用另一个初始化程序,但是我认为除了初始化父级以外,这是不可能的,因为required init()
是一个指定的初始化程序,不能在同一类中链接,只能方便初始化程序可以链接在同一类中。
您可以将协议扩展名ìnit
视为便利初始化器,因为初始化需要调用另一个初始化器,就像其他便利初始化器对self.init(...)
一样。
答案 2 :(得分:0)
您所做的完全错误。协议不是超类。
协议的默认实现只是未实现协议必需方法时使用的默认设置。您不能通过任何方式直接调用协议的默认实现。
协议不是超类的简单替代。根据协议更改思维方式。
即使我知道实例方法也是可能的。
您正在错误地做某事。即使它是方法,也不能调用协议的默认实现。