Rob
Rob

Reputation: 4224

Swift: how to avoid rewriting this init() in all inheriting classes?

I have this class and protocol in a framework:

public protocol P {}

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

And in the project using this framework:

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

The thing that bugs me is that for every class that inherits C, I need to define the same init() like this:

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

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

// etc...

Is there a way for me to declare this default init in my project, like using an extension this way:

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

This way, I would simply call C1(), C2() etc without defining it in the subclass.

Thanks for your help.

Upvotes: 0

Views: 123

Answers (2)

gmogames
gmogames

Reputation: 3081

You could create a protocol that contains the init, extend the protocol and provide a default implementation, and assign the protocol to 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
}

Or if you don't want another protocol, you will need a new class that implements the init and subclass C and have your C1 and C2 inherit this new class. Its what is usually done when people create BaseUIViewController and make their UIViewControllers subclasses of this:

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
}

Upvotes: 1

JeremyP
JeremyP

Reputation: 86651

Declare a convenience initialiser

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

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

Or you can put the convenience initialiser in the main definition of C.

Upvotes: 0

Related Questions