0

I am teaching myself Swift and I have come across a problem that I do not quite understand. I am using the official Swift manual. In the manual there is a protocol named Shape that has one requirement:

protocol Shape {
    func draw() -> String
}

There is a struct called Triangle which conforms to Shape, from which we will create a variable called smallTriangle:

struct Triangle: Shape {
    var size: Int
    
    func draw() -> String {
        var result = [String]()
        for length in 1...size {
            result.append(String(repeating: "*", count: length))
        }
        return result.joined(separator: "\n")
    }
}

let smallTriangle = Triangle(size: 3)

There is a generic struct named FlippedShape that conforms to Shape that accepts a generic parameter T that also conforms to Shape. The struct flips any shape that is passed to it:

struct FlippedShape<T: Shape>: Shape {
    var shape: T
    
    func draw() -> String {
        let lines = shape.draw().split(separator: "\n")
        return lines.reversed().joined(separator: "\n")
    }
}

There is a generic function called protoFlip which has a generic parameter T that conforms to Shape and has a return type of Shape, an instance of FlippedShape to be specific:

func protoFlip<T: Shape>(_ shape: T) -> Shape {
    return FlippedShape(shape: shape)
}

An attempt to pass small triangle to this function and nest it results in an error:

protoFlip(protoFlip(smallTriangle))

The manual says that it is because:

"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(_:)."

I can't say I understand why this is so. The protoFlip function accepts a generic parameter of type Shape, and returns an instance that conforms to Shape, so why exactly would that instance that is returned be considered an invalid argument to protoFlip? I especially didn't understand the phrase "However, a value of a protocol type doesn’t conform to that protocol". What does this mean?

TylerP
  • 9,600
  • 4
  • 39
  • 43
  • 1
    Protocols don't conform to protocols, including themselves. So, when `protoFlip` returns a `Shape`, that doesn't fit with what its parameter needs, which is a type conforming to `Shape`, but `Shape` doesn't conform to `Shape`. Instead, `protoFlip` should return `some Shape` - which is called an opaque type, but what it means is that it's some type that conforms to `Shape` as will be defined by the function (callee) – New Dev Feb 06 '21 at 00:42
  • 1
    See Hamish's answer in the duplicate. – Sweeper Feb 06 '21 at 02:01

0 Answers0