不透明类型
in 技术 with 0 comment

不透明类型

in 技术 with 0 comment

具有不透明返回类型的函数或方法隐藏其返回值的类型信息。不是提供具体类型作为函数的返回类型,而是根据它支持的协议来描述返回值。隐藏类型信息在模块和调用该模块的代码之间的边界很有用,因为返回值的底层类型可以保持私有。与返回类型为协议类型的值不同,不透明类型保留类型标识——编译器可以访问类型信息,但调用该模块的代码却不能。

不透明类型解决的问题

例如,假设您正在编写一个绘制 ASCII 图形形状的模块。ASCII 图形形状的基本特征是一个 draw() 函数,它返回字符串以表示该形状,您可以将该函数定义为 Shape 协议的方法:

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")
    }
}
let smallTriangle = Triangle(size: 3)
print(smallTriangle.draw())
// *
// **
// ***

您可以使用泛型来实现像垂直翻转形状这样的操作,如下面的代码所示。然而,这种方法有一个重要的限制:公开了用于创建 FlippedShape 的确切泛型类型。

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

通过定义 JoinedShape<T: Shape, U: Shape> 这种结构体,将两个形状垂直连接在一起,如下面的代码所示,会产生 JoinedShape<Triangle, FlippedShape<Triangle>> 这样的类型,将翻转的三角形与另一个三角形连接起来。

struct JoinedShape<T: Shape, U: Shape>: Shape {
    var top: T
    var bottom: U
    func draw() -> String {
        return top.draw() + "\n" + bottom.draw()
    }
}
let joinedTriangles = JoinedShape(top: smallTriangle, bottom: flippedTriangle)
print(joinedTriangles.draw())
// *
// **
// ***
// ***
// **
// *

由于需要声明完整的返回类型,公开关于创建形状的详细信息,导致不属于 ASCII 图形模块的公共接口的类型泄漏。模块内部的代码可以以各种方式构建相同的形状,而调用该形状的模块外部的其它代码不必考虑有关形状构建的实现细节。像 JoinedShapeFlippedShape 这样的包装器类型对模块的使用者来说并不重要,而且它们不应该是可见的。该模块的公共接口由连接和翻转形状等操作组成,这些操作返回另一个 Shape 值。

返回不透明类型

您可以将不透明类型视为与泛型类型相反的类型。泛型类型让调用函数的代码选择该函数参数的类型并以一种从函数实现中抽象出来的方式返回值。例如,以下代码中的函数返回一个依赖于其调用者的类型:

func max<T>(_ x: T, _ y: T) -> T where T: Comparable { ... }

码的呼叫max(_:_:)选择的值x和y,和这些值的类型决定的具体类型T。调用代码可以使用任何符合Comparable协议的类型。函数内部的代码以通用方式编写,因此它可以处理调用者提供的任何类型。实现max(_:_:)仅使用所有Comparable类型共享的功能。

对于具有不透明返回类型的函数,这些角色是相反的。不透明类型允许函数实现以一种从调用函数的代码中抽象出来的方式为它返回的值选择类型。例如,以下示例中的函数返回一个梯形而不暴露该形状的基础类型。

翻译自:https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html

Responses