When I work on the opaque types, I read this section in the official documents of Swift.
Another problem with this approach is that the shape transformations don’t nest. The result of flipping a triangle is a value of type Shape, and the protoFlip(:) function takes an argument of some type that conforms to the Shape protocol. However, a value of a protocol type doesn’t conform to that protocol; the value returned by protoFlip(:) doesn’t conform to Shape. This means code like protoFlip(protoFlip(smallTriange)) that applies multiple transformations is invalid because the flipped shape isn’t a valid argument to protoFlip(_:).
This part made me consider about nested functions whose return type is protocol and I wanted to play about the protocol return types in the playground. As a result, I created a protocol called Example and also, a non generic and generic concrete types that conform to Example protocol. I kept "sample" method implementations which is protocol requirement as simple as possible because of focusing return types.
protocol Example {
func sample(text: String) -> String
}
struct ExampleStruct: Example {
func sample(text: String) -> String {
return text
}
}
struct ExampleGenericStruct<T: Example>: Example {
var t: T
func sample(text: String) -> String {
return t.sample(text: "\n")
}
}
After that, I created a generic function which has an argument constraint by Example protocol and returns Example protocol. Then, I tested my function as nested.
func genericTestExample<T: Example>(example: T) -> Example {
return ExampleGenericStruct(t: example)
}
genericTestExample(example: genericTestExample(example: ExampleStruct()))
I got this error:
Value of protocol type 'Example' cannot conform to 'Example'; only struct/enum/class types can conform to protocols
This is what I expected. Function returns the protocol itself, not the concrete type that conforms it.
Finally, I wrote an another function.
func testExample(example: Example) -> Example {
if example is ExampleStruct {
return example
}
return ExampleGenericStruct(t: ExampleStruct())
}
When I run the code, I could nest this function successfully.
testExample(example: testExample(example: ExampleStruct()))
I can pass any value to both genericTestExample and testExample functions as long as it conforms to Example protocol. Also, they have the same protocol return type. I don't know why I could nest testExample function while I could not nest genericTestExample function or vise versa.
testExampleaccepts a parameter of typeExample, which is also its return value - that's why it works here.genericTestExample, on the other hand, accept a parameter of typeT: Example, but returnsExample- which, as you noted, is not accepted becauseExampledoesn't conform toExample- a requirement ofT- New Dev