Swift - Opaque Type
Published: 2022-04-07 05:29:34

###Opaque Type

A function or method with an opaque return type hides its return value’s type information.

- Unlike returning a value whose type is a protocol type, opaque types preserve type identity—the compiler has access to the type information, but clients of the module don’t.

- To declares a function/method's  return type as opaque use **some** keyword.

example :

``` swift
protocol Shape {
    func draw() -> String
}

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")
    }
}

struct Square: Shape {
    var size: Int
    func draw() -> String {
        let line = String(repeating: "*", count: size)
        let result = Array<String>(repeating: line, count: size)
        return result.joined(separator: "\n")
    }
}

let smallTriangle = Triangle(size: 3)
```

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

struct JoinedShape<T: Shape, U: Shape>: Shape {
    var top: T
    var bottom: U
    func draw() -> String {
        return top.draw() + "\n" + bottom.draw()
    }
}
```

``` swift
func flip<T: Shape>(_ shape: T) -> some Shape {
    return FlippedShape(shape: shape)
}
func join<T: Shape, U: Shape>(_ top: T, _ bottom: U) -> some Shape {
    JoinedShape(top: top, bottom: bottom)
}

let opaqueJoinedTriangles = join(smallTriangle, flip(smallTriangle))
print(opaqueJoinedTriangles.draw())
// *
// **
// ***
// ***
// **
// *
```


If a function with an opaque return type returns from multiple places, all of the possible return values must have the same type. For a generic function, that return type can use the function’s generic type parameters, but it must still be a single type. 

example - compile error:

``` swift
func makeShape(shape : String) ->  some Shape { // Function declares an opaque return type, but the return statements in its body do not have matching underlying types
    if(shape == "square"){
        print("here")
        return Square(size : 4)
    }else{
        return Triangle(size : 4)
    }
    
    
}

let shape =  makeShape(shape: "square")
```
---

### Differences Between Opaque Types and Generic Types

- Generic types let the code that calls a function pick the type for that function’s parameters and return value in a way that’s abstracted away from the function implementation

- An opaque type lets the function implementation pick the type for the value it returns in a way that’s abstracted away from the code that calls the function.

### Differences Between Opaque Types and  Protocol Types
- An opaque type refers to one specific type, although the caller of the function isn’t able to see which type.

- A protocol type can refer to any type that conforms to the protocol. 

- Swift can infer associated types, which lets you use an opaque return value in places where a protocol type can’t be used as a return value.