在Swift-protocol

时间:2016-08-06 19:17:11

标签: arrays swift generics protocols type-constraints

我有一个逐行输出像素的对象(就像旧电视那样)。该对象只是将字节写入二维数组。因此存在多条水平线,每条水平线具有多个像素。这些数字是固定的:有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学习,使用泛型可以帮助编译器生成最佳代码。有没有办法让我使用泛型来生成更高效的代码,然后使用普通协议作为一种类型?

1 个答案:

答案 0 :(得分:0)

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

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

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

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