【问题标题】:Require an Array to be a minimum size in Swift-protocol要求数组是 Swift 协议中的最小大小
【发布时间】:2016-08-06 19:17:11
【问题描述】:

我有一个对象可以逐行输出像素(就像旧电视一样)。该对象只是将字节写入二维数组。所以有许多水平线,每条都有许多像素。这些数字是固定的:有 x 条水平线,每条线有 y 条像素。一个像素是一个由红、绿、蓝组成的结构体。

我希望此类的客户插入他们自己的对象,这些值可以写入其中,因为我希望这两个代码在 Apple 平台(存在 CALayer)上运行良好,但也适用于其他平台(例如 Linux,需要在没有 CALayer 的情况下完成渲染)。所以我想制定这样的协议:

struct Pixel
{
    var red: UInt8 = 0
    var green: UInt8 = 0
    var blue: UInt8 = 0
}
protocol PixelLine
{
    var pixels: [Pixel] { get }
}
protocol OutputReceivable
{
    var pixelLines: [PixelLine] { get }
}

这些协议将在某些时候使用,例如

let pixelLineIndex = ... // max 719
let pixelIndex = ... // max 1279

// outputReceivable is an object that conforms to the OutputReceivable protocol
outputReceivale.pixelLines[pixelLineIndex][pixelIndex].red = 12
outputReceivale.pixelLines[pixelLineIndex][pixelIndex].green = 128
outputReceivale.pixelLines[pixelLineIndex][pixelIndex].blue = 66

出现两个问题:

  • 如何要求 PixelLine 协议在数组中至少有 1280 个像素单元,而协议 OutputReceivable 在数组中至少有 720 个 PixelLine 元素?

  • 正如我从a video 中学到的,使用泛型可以帮助编译器生成最佳代码。有没有办法让我使用泛型来生成性能更高的代码,然后使用普通协议作为类型?

【问题讨论】:

    标签: arrays swift generics protocols type-constraints


    【解决方案1】:

    Swift 中没有依赖类型。您不能直接要求数组具有最小大小。您可以做的是创建只能使用特定数据构建的新类型。所以在这种情况下,更好的模型是使PixelLine 成为结构而不是协议。然后你可以有一个init?,在使用它之前确保它是合法的。

    围绕数组的简单结构包装器的内存成本为零,调度成本极低。如果您正在处理高性能系统,那么包装 Array 的结构是一个很好的起点。

    struct PixelLine {
        let pixels: [Pixel]
        init?(pixels: [Pixel]) {
            guard pixels.count >= 1280 else { return nil }
            self.pixels = pixels
        }
    }
    

    您可以像这样直接公开pixels,也可以使PixelLine 成为一个集合(甚至只是一个序列),将其所需的方法转发给pixels

    【讨论】:

    • 我想到了这个选项,但这样客户将无法将自己的实例插入到我的像素输出对象中。使用您的建议,像素输出将是输出实例的出售,从而降低在客户端进行转换的效率(例如倒置坐标空间、不同颜色空间、缩放、转换等)。我希望此类的客户在设置值时允许这种转换。
    • 顺便问一下,您对何时使用guard pixels.count >= 1280 ...precondition(pixels.count == 1280) ... 有什么想法?
    • 您所设想的方式在 Swift(或我所知道的任何主流语言;它被称为依赖类型,通常是语言设计中的一个研究课题)中是不可能的。您最好的工具是将 Line 包装在具体类型(结构)而不是协议中。它可以接受一个集合而不是一个数组来给调用者更多的灵活性。一个初始化?如果您从文件/网络中读取,通常比前提条件要好。如果期望调用者在代码中生成数据,则前置条件会更好。取决于用例。但在 Swift 编译时无法解决。
    • 自从我问起已经过去了 5 年......我一直都采用你的方法,所以接受你的回答。对我疏忽给予应得的信用表示歉意。
    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多