Swift protocol defining a class method returning itself

I had code that worked in beta version of Xcode 6, but recently stopped working after upgrading to xcode 6.1.

This is my protocol:

protocol CanDeserialiseFromJson { class func FromJson(json : JSONValue) -> Self } 

This is the implementation:

 extension Invoice : CanDeserialiseFromJson { class func FromJson(json : JSONValue) -> Self { return Invoice() } } 

This does not give an error:

 'Invoice' is not convertable to 'Self' 

As I said, it worked, and I can’t understand why it doesn’t work anymore

+6
source share
3 answers

Self in a protocol is a requirement that protocol implementations use their own type. Since Invoice is the type in which you accept the protocol, your FromJson implementation must have an Invoice return type.

+2
source

It is right. Your method is declared to return Self , while you return Invoice . Class methods are inherited, and Self subclasses will have this type of subclass, and Invoice not a subtype of this type.

To really return Self , if Invoice has the required init() constructor, you can do something like this:

 extension Invoice : CanDeserialiseFromJson { class func FromJson(json : JSONValue) -> Self { return self() } } 
+4
source

In case you really need to return Self (in my case, I have the Objective-C protocol, which translates the method into a fast function that returns Self), and not mark your class as final, you need to create the required initializer and use it:

 class Foo { static func bar() -> Self { return self.init() } required init() { } } 

The final / required requirement comes from the fact that you can subclass this class and have a different initializer. Final removes the parameter for the subclass, while the required init ensures that any subclass will implement the required initializer used in the static method.

0
source

Source: https://habr.com/ru/post/976385/


All Articles