Swift中的下标和协议

3
我正在定义一个协议,为了抽象目的,它有一个“下标”函数,具有getter和setter。然后我定义了一个实现该协议的类。
问题简述:如果我在类的对象上使用下标(作为左值,因此使用setter),则一切都按预期工作。如果我在仅声明为协议类型的对象上执行它,则会出现“无法将结果分配给此表达式”的错误。
问题详述:我有一个Int类型的棋盘,这是一个二维矩阵。我通过BoardType协议公开了Board类型。
protocol BoardType {
    var width: Int { get }
    var height: Int { get }
    subscript(x: Int, y: Int) -> Int { get set }
}

class Board: BoardType {

    let width, height: Int
    var matrix: Array2D<Int>

    init(width: Int, height: Int) {
        self.width = width
        self.height = height
        matrix = Array2D<Int>(cols: width, rows: height, defaultValue: 0)
    }

    subscript(x: Int, y: Int) -> Int {
        get {
            return matrix[x, y]
        }
        set {
            matrix[x, y] = newValue
        }
    }
}

Array2D的实现是标准的:

class Array2D<T> {

    var cols: Int, rows: Int
    var matrix: [T]

    init(cols: Int, rows:Int, defaultValue: T) {
        self.cols = cols
        self.rows = rows
        matrix = Array(count: cols*rows, repeatedValue: defaultValue)
    }

    subscript(x: Int, y: Int) -> T {
        get {
            return matrix[cols * y + x]
        }
        set {
            matrix[cols * y + x] = newValue
        }
    }

    func colCount() -> Int {
        return self.cols
    }

    func rowCount() -> Int {
        return self.rows
    }
}

现在,如果我按照以下方式操作,它可以正常工作:
    let board = Board(width: 4, height: 4)
    board[1, 1] = 10

然而,如果我使用原型,就会出现错误。

    let board : BoardType = Board(width: 4, height: 4)
    board[1, 1] = 10

为什么?
1个回答

20
编译器之所以这样做是因为您使用了let声明第二个,它可能是一个值类型,此时下标设置器将成为一个变异表达式。有两种解决方法-在使用BoardType进行声明时要么使用var
var board : BoardType = Board(width: 4, height: 4)
board[1,1] = 10

或者将 BoardType 定义为类协议:
protocol BoardType: class {
    var width: Int {get}
    var height: Int {get}
    subscript(x:Int, y:Int) -> Int {get set}
}

谢谢,它有效了!我之前不知道类协议。记录一下,我的协议也符合 Printable,为了使它成为类协议,正确的语法似乎是 protocol BoardType : class, Printable - Maiaux
没错 - 应该给你一个关于仅类协议的文档链接 - Nate Cook
正确的答案。它是有意义的,但这个错误信息太令人困惑了。最新的Swift给了我一个错误,显示“无法对类型为<ProtocolName>的值进行下标操作”,但没有更多的信息。 - funkybro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接