Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour of Protocols with Self

I was recently reading Protocols, Generic Type Constraints and Arrays in Swift. My question concerns the following two examples from the blog:

The code:

protocol MyProtocol1 {
    var myValue: Self { get }
}

let array: [MyProtocol1] = []  // Error.

Produces the error:

Protocol 'MyProtocol1' can only be used as a generic constraint because it has Self or associated type requirements.

That's expected and there have been several SO questions concerning the topic. However, by changing myValue to a function there's no longer any error, yet in both cases Self is returned.

protocol MyProtocol2 {
    func myValue() -> Self
}

let array: [MyProtocol2] = []  // This is okay.

Does anyone know the cause of this seemingly strange behaviour?

like image 489
ABakerSmith Avatar asked May 06 '15 12:05

ABakerSmith


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.

What is a protocol in Swiftui?

In Swift, a protocol defines a blueprint of methods or properties that can then be adopted by classes (or any other types).


1 Answers

It's explained about 18 minutes into this video: https://developer.apple.com/videos/wwdc/2015/?id=408

Because your protocol references "self" it can only be used as a generic constraint not as a type.

Example: Let's say 2 structs implement your protocol - Duke & Silver.

If you made an array of protocol2 ([protocol2]), then your array could contain either Dukes are Silvers.

myValue specifically states that the return value must be self. This means that a Duke must return a Duke and a Silver must return a Silver. As such, you can't have Dukes & Silvers in the same array because their MyValue functions have different return values.

To fix the issue, you can either:

1) Make the return type of myValue protocol2 so that Dukes and Silvers both just return a protocol2 type

2) Make an array of generics that conform to protocol2

like image 158
JoeyBartez Avatar answered Sep 17 '22 15:09

JoeyBartez