Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to satisfy a protocol which includes an initializer?

I defined a simple class:

class MyClass {     var name:String?      required init() {         println("init")     } } 

I can add a new initializer in an extension like this:

extension MyClass {     convenience init(name: String) {         self.init()         self.name = name     } } 

Everything works fine.

But as soon as I define the new initializer in a protocol:

protocol MyProtocol {     init(name:String) } 

And make my extension confirm to that protocol:

extension MyClass : MyProtocol {     convenience init(name: String) {         self.init()         self.name = name     } } 

I get the following error:

Initializer requirement 'init(name:)' can only be satisfied by a required initializer in the definition of non-final class 'MyClass'

What is going on here?

(BTW: I can't make my class final, because this is only the extract of a more complicated use case.)

like image 239
Klaas Avatar asked Oct 26 '14 22:10

Klaas


People also ask

Is it possible to prevent the adoption of a protocol by a struct?

A protocol defines a blueprint of methods, properties, and other requirements. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. But there would be a time when you want to restrict protocols to be adopted by a specific class.

Why do we need convenience initializer of the same task can be obtained with designated initializer?

A convenience initializer is a secondary initializer that must call a designated initializer of the same class. It is useful when you want to provide default values or other custom setup. A class does not require convenience initializers.

What does an initializer do?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }

What must a convenience initializer call?

The convenience initializer must call one of the two designated initializers, because it can only call another initializer from the same class. This satisfies rules 2 and 3 from above. Both designated initializers must call the single designated initializer from the superclass, to satisfy rule 1 from above.


1 Answers

Ok, my bad.

To guarantee that all subclasses conform to MyProtocol new initializer has to be marked as required as well.

Furthermore Swift requires to declare all required initializers directly within the class and does not allow to declare them in extensions.

extension MyClass : MyProtocol {     required convenience init(name: String) {         self.init()         self.name = name     } } 
like image 60
Klaas Avatar answered Sep 28 '22 01:09

Klaas