Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializers in protocols in Swift must be designated. Why is that so?

If you try to create a protocol in Swift that includes a convenience initialiser, you will be immediately scolded by the compiler:

protocol Zizo{
    convenience init(a:String, b:Int)
}

Convenience initializer not allowed in non class type.

Is there any reason for this limitation? It just doesn't make sense to me.

What could possibly go wrong?

like image 394
cfischer Avatar asked Nov 12 '14 12:11

cfischer


People also ask

What are initializers in Swift?

Swift defines two kinds of initializers for class types to help ensure all stored properties receive an initial value. These are known as designated initializers and convenience initializers. Designated initializers are the primary initializers for a class.

How does the Swift compiler decide which init method to call?

The swift compiler will decide which init method to call based on the argument label. Swift defines two kinds of initializers for class types to help ensure all stored properties receive an initial value. Designated initializers are the primary initializers for a class.

What is an argument label in Swift initializers?

Because of this, Swift provides an automatic argument label for every parameter in an initializer if you don’t provide one. The following example defines a structure called Color, with three constant properties called red, green, and blue.

Why is the init () method provided as a designated initializer?

The init (name: String) initializer from the Food class is provided as a designated initializer, because it ensures that all stored properties of a new Food instance are fully initialized. The Food class doesn’t have a superclass, and so the init (name: String) initializer doesn’t need to call super.init () to complete its initialization.


2 Answers

It's because, it makes no sense. protocol only defines implementers have required methods and properties. It does not define implementation detail. When protocol requires init(a:String, b:Int), you can implement it as either designated or convenience initializer, as you like.

protocol Zizo{
    init(a:String, b:Int)
}

class Foo:Zizo {
    init() {
    }
    convenience required init(a:String, b:Int) {
        self.init()
    }
}
class Bar:Foo {
    override convenience init() {
        self.init(a:"baz", b:42)
    }
    required init(a:String, b:Int) {
        super.init()
    }
}

As you can see, protocol forces init(a:String, b:Int) being required initializer, but does nothing about "convenience" or "designated".

like image 141
rintaro Avatar answered Oct 07 '22 04:10

rintaro


In case you'd still like to do this, you could consider putting a static function in the protocol instead:

protocol Zizo {
     static func make(withA a: String, b: Int) -> Self
}

this does get a little hairy when used in a class inheritance tree.

like image 29
Menno Avatar answered Oct 07 '22 04:10

Menno