子类的Swift数组处理

时间:2014-08-09 16:32:56

标签: objective-c arrays swift subclass implicit-conversion

如果我有一个声明为var gameBoard: [Piece] = []的变量,有没有办法将Piece的子类Queen添加到数组中?

我使用Piece代表所有作品。 Queen,Pawn,Bishop等都是Piece的子类,应该包含在棋盘上。

我记得在Objective C中经常这样做,其中子类可以用来代替超类。但在我的第一次尝试中,我收到错误说

'@lvalue $T11' is not identical to 'Piece`

这不可能了吗?或者是否需要使用一些我现在想不到的泛型?

修改

这是我的董事会的实施,仅包括相关部分。

struct GameBoard{

    var board: [[Piece]]

    init() {
        board = []
        for _ in 0...7{
            var collumn: [Piece] = []
            for _ in 0...7{
                var piece = Piece(player: .None, board: self)
                collumn.append(piece)
            }
            board.append(collumn)
        }
    }

    subscript(coords:(Int, Int) ) -> Piece {
        return board[coords.1][coords.0]
    }
}

失败的代码是

var board = GameBoard()
var q = Queen(player: .Black, board: board)
board[(4,5)] = q         //Throws the error
board.board[5][4] = q    //Works

在我看来,这两个应该以同样的方式工作。这可能是订阅的问题,但我不完全确定。

3 个答案:

答案 0 :(得分:5)

只是为了跟进您的编辑,这在Swift中运行良好。例如:

class Piece {}
class Bishop : Piece {}
let pieces: [Piece] = [Bishop()]

你有一个不起作用的例子吗?

请注意,当您在错误中看到@lvalue $T##时,通常意味着您正在尝试修改常量。犯这个错误的一个简单方法是尝试修改传递给您的数组,并且没有标记var。例如,请参阅Swift function that takes in array giving error: '@lvalue $T24' is not identical to 'CGFloat'

答案 1 :(得分:1)

以下是我写它的方式。包括关于下标和奖励的问题的答案,使用Coords结构代替元组(例如允许实现Printable)并为每个方块使用选项(允许nil用作空方块的表示。)< / p>

class Piece : Printable {
    var description: String { get { return "Piece" } }
}

class Queen : Piece {
    override var description: String { get { return "Queen" } }
}

struct Coords : Printable {
    let column: Int
    let row: Int

    init(_ column: Int, _ row: Int) {
        self.column = column
        self.row = row
    }

    var description: String { get { return "Coords(\(column), \(row))" } }
}

struct GameBoard {
    var board: [[Piece?]]

    init() {
        board = []
        for _ in 1...8 {
            board.append(Array<Piece?>(count: 8, repeatedValue:nil))
        }
    }

    subscript(c: Coords) -> Piece? {
        get {
            return board[c.column][c.row]
        }

        set (newValue) {
            board[c.column][c.row] = newValue
        }
    }
}

func testGameBoard() {
    var board = GameBoard()

    board[Coords(4, 5)] = Queen()

    func printSquare(coords: Coords) {
        if let p = board[coords] {
            println("At \(coords) is a \(p)")
        } else {
            println("At \(coords) is an empty square")
        }
    }

    printSquare(Coords(4, 5)) // Prints: At Coords(4, 5) is a Queen
    printSquare(Coords(4, 6)) // Prints: At Coords(4, 6) is an empty square
}

答案 2 :(得分:0)

只要QueenPiece的子类,就没有问题。就这样:

class Piece {}
class Queen : Piece {}

class Board {
  var board : [[Piece?]] = 
    { var board : [[Piece?]] = []
      for _ in 0..<8 { board.append (Array<Piece?>(count: 8, repeatedValue:nil)) }
      return board } ()

  subscript (row:Int, col:Int) -> Piece? {
    get { return board[row][col] }
    set { board[row][col] = newValue }}
}

然后用作:

 23> let board = Board()
 24> b[0,4] = Queen()
 25> b[7,4] = Queen()
 26> b
$R0: Board = {
  board = 8 values {
    [0] = 8 values {
      [0] = nil
      [1] = nil
      [2] = nil
      [3] = nil
      [4] = Some
      [5] = nil
      [6] = nil
      [7] = nil
    } ...
相关问题