4

If I have a variable declared like var gameBoard: [Piece] = [], is there any way to add a subclass of Piece, called Queen, to the array?

I am using Piece to represent all pieces. Queen, Pawn, Bishop and such are all subclasses of Piece, and should be included on the board.

I remember doing this frequently in Objective C, where subclasses were able to be used in place of the superclass. But in my first attempts, it I am getting an error saying

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

Is this not possible anymore? Or would there need to be some use of generics that I cannot think of right now?

Edit

Here is the implementation of my board, including only the relevant parts.

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]
    }
}

The code that fails is

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

It seems to me that these two should work the same way. It may be an issue with the subscripting, but I am not completely sure.

1
  • 1
    This works fine in Swift. Can you give an actual example that does not work as expected? Commented Aug 9, 2014 at 16:44

3 Answers 3

5

Just to followup on your edits, this works fine in Swift. For example:

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

Do you have an example that does not work?

As a note, when you see @lvalue $T## in your errors, it often means you're trying to modify a constant. An easy way to make that mistake is to try to modify an array that was passed to you and that you did not mark var. For example, see Swift function that takes in array giving error: '@lvalue $T24' is not identical to 'CGFloat'.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, I should use a different example. I will update my question.
I added the code that is failing, and relevant implementation details. Hopefully this might clear things up.
Seems that I forgot to create a setter for the subscript. That might be what is making it read-only
1

Here is how I would write it. Includes answer to the question about subscripting, and for bonus, uses a Coords struct in place of tuples (allows implementation of Printable for example) and uses optionals for each square (allows nil to be used as the representation of an empty square.)

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 Comments

Is it really possible with {struct Coords : Printable}?
@wagashi Yes, it absolutely is, but if you're trying to test the above in a playground, note that the most recent Xcode beta still doesn't honor the Printable protocol for instances displayed within the playground.
0

As long as Queen is a subclass of Piece then there would be no problem. As such:

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 }}
}

and then use as:

 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
    } ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.