Java - 使用受保护的方法从不同的 class 更新对象的属性
Java - Update attributes of an object from a different class with protected methods
我正在尝试交换网格中的片段(或单元格)。
我有 class 具有坐标(在板上的位置)等属性的单元格。此 class 具有受保护的方法 setCoordinate。
我还有class关卡,有棋盘等属性(由classCell的很多物体组成),还有换棋子的方法。它还具有类似 getCell 的方法,用于在给定网格中的坐标的情况下检索单元格对象。
所以,如果我创建一个单元格对象,例如:
Cell cell1 = (Cell) getCell(new Coordinate(2, 2));
Cell cell2 = (Cell) getCell(new Coordinate(1, 1));
当我交换棋子时
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
setCell(secondCoord,getCell(firstCoord));
setCell(firstCoord,getCell(secondCoord));
}
我可以将单元格 1 放在单元格 2 的位置,将单元格 2 放在单元格 1 的位置。但是,每个单元格的坐标不会根据板中的新位置更新。
我无法使用 class 单元格中的 setCoordinate 方法,因为它受到保护,而且我无法创建 public 方法。我不确定原因,但我仍在学习,这是给定的要求。
如何实现坐标也更新的交换?
以下是我的代码的一些相关和简化部分:
public class Level {
private Cell[][] board;
public Level(String fileName) {
parse(fileName);
}
private void parse(String fileName) {
... fills board...
}
public Cell getCell(Coordinate coord) {
return board[coord.getRow()][coord.getColumn()];
}
private void setCell(Coordinate coord, Cell cell) {
board[coord.getRow()][coord.getColumn()] = cell;
}
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
setCell(secondCoord,getCell(firstCoord));
setCell(firstCoord,getCell(secondCoord));
}
}
}
public class Cell {
private Coordinate coordinate;
public Cell(int row, int column) {
setCoordinate(row,column);
}
public Coordinate getCoordinate() { return this.coordinate; }
protected void setCoordinate(int row, int column) {
this.coordinate = new Coordinate(row,column);
}
}
public class Coordinate {
private int row;
private int column;
public Coordinate(int row, int column) {
setRow(row);
setColumn(column);
}
public int getRow() { return this.row; };
private void setRow(int row) {
this.row = row;
}
public int getColumn() {return this.column; }
private void setColumn(int column) {
this.column = column;
}
}
编辑:
仔细研究之后,我的问题似乎是,当我进行交换时,我将一块新棋子分配给棋盘中的一个单元格,而不是真正交换。最终的棋盘是正确的,但我一直在重新创建棋子而不是交换棋子。
所以,稍微简化一下,将 (0,0) 中的片段与 (1,1) 中的片段交换,我这样做:
board[0][0] = getCell(1,1);
board[1][1] = getCell(0,0);
但是我正在为选定的位置创建新作品。
我测试的是这样的:
Cell cell1 = getCell(0,0);
Cell cell2 = getCell(1,1);
swapCells(cell1.getCoordinate(), cell2.getCoordinate());
assertEquals("(1,1)", cell1.getCoordinate().toString());
但是 assertequals 失败了,因为它们在这些对象 cell1 和 cell2 上,但我并没有真正使用这些对象,只是创建了看起来像它们的新对象。此外,swapCells 方法没有 Cell 对象作为参数。我真的不知道该怎么做。
您有两个问题需要解决。
- 更改
Cell
对象在 board
数组中的位置。
- 交换时更新
Cell
对象的内部数据。
第一个你已经完成了。要达到第二个,您至少需要能够执行以下选项之一。
- 可以访问更新数据的方法,或者
- 有一个可以为您更新数据的委托对象,或者
- 给人一种发生交换的错觉,或者
- 使用反射(不推荐)
您提到您受到给定要求的限制,您不能更改对所需方法的访问。因此,这不是一个选项。
创建委托对象(在此上下文中)意味着您将需要扩展 Cell
class 并允许通过子 class 访问其受保护的方法。这对我来说似乎是一个黑客。我不认为这是执行此操作的正确方法,但它允许您在不真正违反您的要求的情况下进行访问。
第三个选项是我认为你应该做的。为此,您需要做的就是创建原始对象的副本并将它们放在需要去的地方。例如,将单元格二的副本放在单元格一所在的位置,将单元格一的副本放在单元格二所在的位置。
第四个选项我就不解释了。但是,使用反射,您将能够绕过访问限制并操作受保护的数据。如果你愿意,你可以阅读反射。但是,不管我个人对反思的看法如何,它都是一个可以让你实现你想要的东西的选择。
UPDATE:交换数组中的两个元素时,需要执行这个简单的 3 步过程:
- 将元素 1 存储在临时变量中。
- 将元素 2 存储在元素 1 的位置。 (元素 2 变为元素 1)
- 将 TEMPORARY 变量存储在元素 2 的位置(旧元素 1 变为元素 2)。
如果您不将第一个元素存储到临时变量中,您将覆盖第一个元素的数据。在您的情况下,它看起来像这样:
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
Cell temp = getCell(secondCoord); // Saves second cell temporarily
setCell(secondCoord, getCell(firstCoord)); // Saves first cell into second cell's location
setCell(firstCoord, temp); // Sets the temp cell (second cell) into the first cell's location
}
此外,因为您可以访问 Cell
对象,所以即使该方法受到保护,您也可以设置坐标。因此,您的 setter 方法应该是这样的:
private void setCell(Coordinate coord, Cell cell) {
cell.setCoordinate(coord.getRow(), coord.getColumn());
board[coord.getRow()][coord.getColumn()] = cell;
}
我在 Cell
class 中添加了一个“名称”属性,以便于调试(对您而言)。现在,当我 运行 你的代码和我所做的两个更改时,你可以看到以前是 (0,0) 的“cell0”现在是 (2,2) 而 cell8 现在是 (0,0) ;显示这两个单元格交换了位置并更新了它们各自的坐标字段。
我为此执行的 main
方法如下:
public static void main(String[] args) {
Level level = new Level("Level1");
int count = 0;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++ ) {
Coordinate coordinate = new Coordinate(row, col);
Cell cell = new Cell(row, col, "cell" + count++);
level.setCell(coordinate, cell);
}
}
level.swapCells(new Coordinate(0,0), new Coordinate(2,2));
}
我正在尝试交换网格中的片段(或单元格)。
我有 class 具有坐标(在板上的位置)等属性的单元格。此 class 具有受保护的方法 setCoordinate。
我还有class关卡,有棋盘等属性(由classCell的很多物体组成),还有换棋子的方法。它还具有类似 getCell 的方法,用于在给定网格中的坐标的情况下检索单元格对象。
所以,如果我创建一个单元格对象,例如:
Cell cell1 = (Cell) getCell(new Coordinate(2, 2));
Cell cell2 = (Cell) getCell(new Coordinate(1, 1));
当我交换棋子时
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
setCell(secondCoord,getCell(firstCoord));
setCell(firstCoord,getCell(secondCoord));
}
我可以将单元格 1 放在单元格 2 的位置,将单元格 2 放在单元格 1 的位置。但是,每个单元格的坐标不会根据板中的新位置更新。
我无法使用 class 单元格中的 setCoordinate 方法,因为它受到保护,而且我无法创建 public 方法。我不确定原因,但我仍在学习,这是给定的要求。
如何实现坐标也更新的交换?
以下是我的代码的一些相关和简化部分:
public class Level {
private Cell[][] board;
public Level(String fileName) {
parse(fileName);
}
private void parse(String fileName) {
... fills board...
}
public Cell getCell(Coordinate coord) {
return board[coord.getRow()][coord.getColumn()];
}
private void setCell(Coordinate coord, Cell cell) {
board[coord.getRow()][coord.getColumn()] = cell;
}
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
setCell(secondCoord,getCell(firstCoord));
setCell(firstCoord,getCell(secondCoord));
}
}
}
public class Cell {
private Coordinate coordinate;
public Cell(int row, int column) {
setCoordinate(row,column);
}
public Coordinate getCoordinate() { return this.coordinate; }
protected void setCoordinate(int row, int column) {
this.coordinate = new Coordinate(row,column);
}
}
public class Coordinate {
private int row;
private int column;
public Coordinate(int row, int column) {
setRow(row);
setColumn(column);
}
public int getRow() { return this.row; };
private void setRow(int row) {
this.row = row;
}
public int getColumn() {return this.column; }
private void setColumn(int column) {
this.column = column;
}
}
编辑: 仔细研究之后,我的问题似乎是,当我进行交换时,我将一块新棋子分配给棋盘中的一个单元格,而不是真正交换。最终的棋盘是正确的,但我一直在重新创建棋子而不是交换棋子。
所以,稍微简化一下,将 (0,0) 中的片段与 (1,1) 中的片段交换,我这样做:
board[0][0] = getCell(1,1);
board[1][1] = getCell(0,0);
但是我正在为选定的位置创建新作品。
我测试的是这样的:
Cell cell1 = getCell(0,0);
Cell cell2 = getCell(1,1);
swapCells(cell1.getCoordinate(), cell2.getCoordinate());
assertEquals("(1,1)", cell1.getCoordinate().toString());
但是 assertequals 失败了,因为它们在这些对象 cell1 和 cell2 上,但我并没有真正使用这些对象,只是创建了看起来像它们的新对象。此外,swapCells 方法没有 Cell 对象作为参数。我真的不知道该怎么做。
您有两个问题需要解决。
- 更改
Cell
对象在board
数组中的位置。 - 交换时更新
Cell
对象的内部数据。
第一个你已经完成了。要达到第二个,您至少需要能够执行以下选项之一。
- 可以访问更新数据的方法,或者
- 有一个可以为您更新数据的委托对象,或者
- 给人一种发生交换的错觉,或者
- 使用反射(不推荐)
您提到您受到给定要求的限制,您不能更改对所需方法的访问。因此,这不是一个选项。
创建委托对象(在此上下文中)意味着您将需要扩展 Cell
class 并允许通过子 class 访问其受保护的方法。这对我来说似乎是一个黑客。我不认为这是执行此操作的正确方法,但它允许您在不真正违反您的要求的情况下进行访问。
第三个选项是我认为你应该做的。为此,您需要做的就是创建原始对象的副本并将它们放在需要去的地方。例如,将单元格二的副本放在单元格一所在的位置,将单元格一的副本放在单元格二所在的位置。
第四个选项我就不解释了。但是,使用反射,您将能够绕过访问限制并操作受保护的数据。如果你愿意,你可以阅读反射。但是,不管我个人对反思的看法如何,它都是一个可以让你实现你想要的东西的选择。
UPDATE:交换数组中的两个元素时,需要执行这个简单的 3 步过程:
- 将元素 1 存储在临时变量中。
- 将元素 2 存储在元素 1 的位置。 (元素 2 变为元素 1)
- 将 TEMPORARY 变量存储在元素 2 的位置(旧元素 1 变为元素 2)。
如果您不将第一个元素存储到临时变量中,您将覆盖第一个元素的数据。在您的情况下,它看起来像这样:
public void swapCells(Coordinate firstCoord, Coordinate secondCoord) {
Cell temp = getCell(secondCoord); // Saves second cell temporarily
setCell(secondCoord, getCell(firstCoord)); // Saves first cell into second cell's location
setCell(firstCoord, temp); // Sets the temp cell (second cell) into the first cell's location
}
此外,因为您可以访问 Cell
对象,所以即使该方法受到保护,您也可以设置坐标。因此,您的 setter 方法应该是这样的:
private void setCell(Coordinate coord, Cell cell) {
cell.setCoordinate(coord.getRow(), coord.getColumn());
board[coord.getRow()][coord.getColumn()] = cell;
}
我在 Cell
class 中添加了一个“名称”属性,以便于调试(对您而言)。现在,当我 运行 你的代码和我所做的两个更改时,你可以看到以前是 (0,0) 的“cell0”现在是 (2,2) 而 cell8 现在是 (0,0) ;显示这两个单元格交换了位置并更新了它们各自的坐标字段。
我为此执行的 main
方法如下:
public static void main(String[] args) {
Level level = new Level("Level1");
int count = 0;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++ ) {
Coordinate coordinate = new Coordinate(row, col);
Cell cell = new Cell(row, col, "cell" + count++);
level.setCell(coordinate, cell);
}
}
level.swapCells(new Coordinate(0,0), new Coordinate(2,2));
}