调用协议扩展初始化程序

时间:2018-08-13 21:13:11

标签: ios swift swift-protocols protocol-extension

我正在尝试构建一组共享通用初始化代码的类。除了继承之外,我认为协议是必经之路。虽然协议和协议扩展适用于实例和静态方法,但在使其与初始化程序一起使用时遇到了一些麻烦。

假设我们有此协议:

protocol CloudServiceWrapper {

    static var isConfigured: Bool { get }

    init()

    func initialize()

}

现在,我们要在协议扩展中为isConfiguredinit()添加默认实现:

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,因为根据协议定义它是必需的,并且似乎不被认为是协议扩展的“实现”。

实际上,更广泛地说,即使我知道实例方法是可行的,我也找不到显式调用协议扩展的初始化程序的任何方法。

我在做什么错?您知道结合类的初始化程序和协议扩展的初始化程序的任何方法吗?我应该回到类继承而不是协议和扩展上吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

init中的protocolrequired,因此必须明确实现,即无法使用默认实现。

对于“显式调用协议扩展的初始化程序”,您无法实例化协议类型。

我建议为此使用继承。

答案 1 :(得分:2)

Public default init in protocol是一个类似的问题。

尽管协议提供了默认实现,为什么类仍需要具有init?答案是,它没有提供默认的实现,而只是提供了另一个init,这就要求这里存在类init()

  

由于不确定您的协议是否涵盖使用该协议的类的所有成员,因此您在协议中声明的任何初始化器都需要将类的“未知”成员的初始化委托给该类提供的另一个初始化器本身。   Source

您的协议初始化可能会被“ init()”类所遮盖,因此您将无法使用它。可能在类初始化程序/协议的必需初始化程序中添加参数,或者在协议扩展名ìnit()中添加参数。如果该类没有覆盖协议扩展的初始化,则可以使用它来初始化该类。

初始化是必需的,因为可以对类进行子类化,并且不必继承初始化程序,请参见inheritance docinitialization doc under Initializer Inheritance and Overriding。如果不需要初始化,则子类将不再遵守该协议,这是不可取的,因此协议中设置的初始化仅由所需的初始化程序填充。

注意:在required init()中,您尝试调用另一个初始化程序,但是我认为除了初始化父级以外,这是不可能的,因为required init()是一个指定的初始化程序,不能在同一类中链接,只能方便初始化程序可以链接在同一类中。

您可以将协议扩展名ìnit视为便利初始化器,因为初始化需要调用另一个初始化器,就像其他便利初始化器对self.init(...)一样。

答案 2 :(得分:0)


此答案并未指出OP的核心问题。保留在这里只是一个记录


您所做的完全错误。协议不是超类。

协议的默认实现只是未实现协议必需方法时使用的默认设置。您不能通过任何方式直接调用协议的默认实现。

协议不是超类的简单替代。根据协议更改思维方式。

即使我知道实例方法也是可能的。

您正在错误地做某事。即使它是方法,也不能调用协议的默认实现。