DEV Community

Naveen Ragul B
Naveen Ragul B

Posted on

Swift - Opaque Type

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 :

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)
Enter fullscreen mode Exit fullscreen mode
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()
    }
}
Enter fullscreen mode Exit fullscreen mode
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())
// *
// **
// ***
// ***
// **
// *
Enter fullscreen mode Exit fullscreen mode

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:

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")
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)