2010-01-28 16 views
8

He aquí un fragmento de código:¿Java tiene un equivalente de referencia constante?

//Game board is made up of Squares. A player can place GamePieces on a Square. 
    public class CheckersBoard 
    { 
     public boolean PlaceGamePiece(GamePiece gamePiece, int nRow, int nColumn) { 
      return m_theGameBoard[nRow][nColumn].PlaceGamePiece(gamePiece); 
     } 

     private Square[][] m_theGameBoard; 
    } 

Digamos que estoy probando el método PlaceGamePiece (utilizando JUnit) y necesito para acceder al m_theGameBoard para que pueda mirarlo y verificar la gamepiece fue colocado en la correcta Square y tiene los datos correctos.

En C++ Me o bien hacer la clase de prueba un amigo para que pueda acceder al miembro de m_theGameBoard privada, o que tendría una función que devuelve un GameBoard const que no puede ser modificada (porque es const):

const GameBoard& GetGameBoard() const { return m_theGameBoard; } 

Ahora puedo hacer lo que quiera comprobar que quiero hacer en el tablero de juego, pero no puedo modificar el tablero porque es const.

Java no admite el retorno de referencias de referencias o clases de amigos. Entonces mi pregunta es ¿cuál es la forma estándar de Java de hacer esto? ¿Debo simplemente proporcionar un conjunto de accesadores get que me permitan verificar los datos en el Square?

ACTUALIZACIÓN: Terminé escribiendo un método GetPiece como sugirió Kaleb Brasee.

public GamePiece GetGamePiece(Point pt) { 
    return new GamePiece(m_theGameBoard[pt.GetRow()][pt.GetColumn()]); 
} 

Aviso Creo un nuevo objeto GamePiece y lo devuelvo. No devuelvo la referencia interna de GameBoards, por lo tanto, nadie puede modificar el tablero porque solo tienen una copia. ¡Bonito! Gracias por la ayuda chicos, algunos consejos realmente buenos.

FYI: Sigo cambiando los nombres de los objetos cuando los publico aquí, lo siento si eso confundió a alguien.

Respuesta

3

Defina la variable como protected, de modo que si la prueba de la unidad está en el mismo paquete, puede acceder a ella.

Sin embargo, solo agregaría un método público getPiece(int row, int col) que devuelve la pieza en ese cuadrado (o nulo si no hay pieza allí). Es probable que necesite un método así de todos modos, y podría usarlo en sus pruebas.

+0

Tengo la impresión de que proteger es lo mismo que el amigo de c. – Karl

+0

Pero, ¿qué ocurre si una clase que trabaja con el tablero necesita mostrar todas las piezas del tablero (como una clase de GUI que necesita mostrar todas las piezas en el tablero)? ¿Cómo harías sin un método para obtener piezas? En mi aplicación de ajedrez, tengo un método 'Board.pieceOn (Square)' que devuelve una Pieza si hay alguna Pieza presente, o nula si la Plaza está vacía. ¿Sería mejor devolver un mapa de cuadrados ocupados mapeados a Pieces? –

+0

http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html ¿Por qué no se dibujan los objetos, dado un contexto gráfico? Agregue un método 'dibujar' a las piezas (o una subclase de cada pieza, si prefiere mantener el código de UI separado). Creo que 'board.draw (graphics)' and 'piece.draw (graphics)' tiene mucho sentido. Combina esto con la técnica de Holub descrita en el enlace y tienes una buena solución que evita romper la encapsulación. –

1

Sí. Sus opciones básicamente se reducen a tener ya sea:

Square getSquareAtLocation(int row, int col) { ... }; 

o el uso de una de las colecciones de Java que luego se podría pasar a través de Collections.unmodifiableList (...)

(tenga en cuenta que si se ha utilizado una lista multidimensional , también debe tener cuidado de ajustar las Listas internas para asegurarse de que no sean modificables)

Si esto solo se va a utilizar para probar, también puede crear una función que devuelva un copia profunda de la matriz.

2

El modificador de acceso predeterminado para un método o propiedad está "protegido por paquete", lo que significa "visible solo dentro de mi paquete". Por lo tanto, puede emular la semántica de "amistad", mientras mantiene una base de código separada para las pruebas, al tener dos carpetas de origen distintas, pero con la misma estructura de paquete.

src 
|--com 
    | 
    --cchampion 
     | 
     --MyClass.java 
tests 
|--com 
    | 
    --cchampion 
     | 
     --TestMyClass.java 

Luego, dentro de MyClass.java

public class MyClass { 
    private int nonTestedThing; 
    int[][] testedThing; // this is visible to TestMyClass 
    // or 
    // protected int[][] testedThing; 
    // if you want it visible to kids 
} 

Esto no es ideal en ningún aspecto, pero es una forma de hacerlo.

Cuestiones relacionadas