J. Doe
J. Doe

Reputation: 13043

Public default init in protocol

I have this code:

public protocol MyProtocol {
    init()
}

public extension MyProtocol {
    public init() {
        self.init()
    }
}

public final class MyClass: MyProtocol {}

I got an error saying:

Initializer 'init()' must be declared public because it matches a requirement in public protocol 'MyProtocol'

If I remove the access control (public) before final, it works. But why? Is there any way I can let the protocol handle the init? I thought all members of protocols are implicitly public by default.

More strange is that a different init that can only be found in the extension is public by default:

public protocol MyProtocol {
    init()
}

public extension MyProtocol {
    public init() {
        self.init()
    }

    public init(youDoNotHaveToImplementMe: Any) {
        self.init()
    }
}

public final class MyClass: MyProtocol {
    public init() {}
}

As you can see, the new init is actually public. I expected my normal init should be public as well. Why is this not the case?

Upvotes: 2

Views: 723

Answers (1)

Fabian
Fabian

Reputation: 5348

MyClass is supposed to conform to given protocol MyProtocol, even if MyClass is public. But how would MyClass conform to MyProtocol, if MyClass were public but its init not visible from the other module? It would conform to MyProtocol(signature says so) and at the same time not(no visible init).

Since your protocol can't be certain to cover all members of the class that uses it, any initializer you declare in your protocol will need to delegate initialization of the "unknown" members of the class to another initializer provided by the class itself.

Source

Since MyClass‘ default initializer is internal the protocol does not conform to the protocol if no public init is declared in-class while MyClass is public.

Upvotes: 2

Related Questions