Swift:如何避免在所有继承的类中重写此init()?

时间:2019-03-28 09:23:49

标签: swift

我在一个框架中有这个类和协议:

public protocol P {}

open class C {
    public init(_ p: P.Type) {
        //super.init() etc
    }
}

在使用此框架的项目中:

enum E: P {
    // cases...
}

让我感到困扰的是,对于每个继承C的类,我都需要像这样定义相同的init()

final class C1: C {
    init() {
        super.init(E.self)
    }
}

final class C2: C {
    init() {
        super.init(E.self)
    }
}

// etc...

我是否可以在项目中声明默认的init,就像使用扩展名一样

extension C {
    // Declare the init(E.self) here somehow?
}

这样,我将简单地调用C1()C2()等,而不在子类中对其进行定义。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您可以创建一个包含init的协议,扩展该协议并提供默认实现,然后将该协议分配给C。

public protocol P {}

enum E: P {
}

protocol A {
    init(_ p: P.Type)
}

extension A {
    init(_ p: P.Type) {
        // Add a default implementation
        self.init(E.self)
    }
}

class C: A {
    // If you want to override, note you need to add `required`
    required init(_ p: P.Type) {
    }
}

class C1: C {
    // No need to init here
}

或者,如果您不想使用其他协议,则需要一个新类来实现init和子类C,并让您的C1和C2继承这个新类。 人们创建BaseUIViewController并为其创建UIViewControllers子类时通常会这样做:

public protocol P {}

enum E: P {
}

class C {
    init(_ p: P.Type) {
    }
}

class CBase: C {
    // Override and provide default implementation
    override init(_ p: P.Type) {
        super.init(E.self)
    }
}

class C1: CBase {
    // No need to init here
}

class C2: CBase {
    // No need to init here
}

答案 1 :(得分:0)

声明一个convenience initialiser

extension C
{
    public convenience init()
    {
        self.init(E.self)
    }
}

let c1 = C1()
let c2 = C2()

或者您可以将便利初始化程序放在C的主要定义中。