Top

JAVA OOP DAY04

  1. 重写T类和J类的print方法并测试

1 重写T类和J类的print方法并测试

1.1 问题

在TetrominoT和TetrominoJ类中重写父类Tetromino的print方法,并进行测试,控制台输出结果如下所示:

--------打印T型---------
i am a T
(0,4), (0,5), (0,6), (1,5)
- - - - * * * - - - 
- - - - - * - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
--------打印J型---------
i am a J
(0,4), (0,5), (0,6), (1,6)
- - - - * * * - - - 
- - - - - - * - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - -

1.2 方案

首先,在TetrominoT类中,重写print方法。方法的重写要遵循“两同两小一大”规则,“两同”即方法名相同,形参列表相同;“两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;“一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。其次,子类TetrominoT重写的print方法,首先实现在控制台输出"i am a T",然后,使用super关键字调用父类的print方法

然后,在TetrominoJ类中,在该类中重写print方法。仍然遵循上述原则。其次,子类TetrominoJ重写的print方法,首先实现在控制台输出"i am a J",然后,使用super关键字调用父类的print方法。

最后,在TetrominoGame类中进行测试,查看调用方法的情况。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:在TetrominoT类中,重写print方法

首先,重构TetrominoT类,在该类中重写print方法。其次,子类TetrominoT重写的print方法,首先实现在控制台输出"i am a T",然后,使用super关键字调用父类的print方法,代码如下所示:

public class TetrominoT extends Tetromino {
	public TetrominoT(int row, int col) {
		super();
		// 按顺时针方向初始化Cell
		cells[0] = new Cell(row, col);
		cells[1] = new Cell(row, col + 1);
		cells[2] = new Cell(row, col + 2);
		cells[3] = new Cell(row + 1, col + 1);
	}

#cold_bold	@Override
#cold_bold	public void print() {
#cold_bold		System.out.println("i am a T");
#cold_bold		super.print();
#cold_bold	}
}

步骤二:在TetrominoJ类中,重写print方法

首先,重构TetrominoJ类,重写print方法;其次,子类TetrominoJ重写的print方法,首先实现在控制台输出"i am a J",然后,使用super关键字调用父类的print方法。代码如下所示:

public class TetrominoJ extends Tetromino {
	public TetrominoJ(int row, int col) {
		// 按顺时针方向初始化Cell
		cells[0] = new Cell(row, col);
		cells[1] = new Cell(row, col + 1);
		cells[2] = new Cell(row, col + 2);
		cells[3] = new Cell(row + 1, col + 2);
	}

#cold_bold	@Override
#cold_bold	public void print() {
#cold_bold		System.out.println("i am a J");
#cold_bold		super.print();
#cold_bold	}
}

步骤三:测试

重构TetrominoGame类,在其main方法中调用print方法。代码如下所示:

public class TetrominoGame {
	public static void main(String[] args) {
		//测试TetrominoT
		System.out.println("--------打印T型---------");
		Tetromino t = new TetrominoT(0, 4);
#cold_bold		t.print();
		printTetromino(t);
		
		//测试TetrominoJ
		System.out.println("--------打印J型---------");
		Tetromino j = new TetrominoJ(0, 4);
#cold_bold		j.print();
		printTetromino(j);
		
	}

	/**
	 * 打印出游戏所在的平面(宽10格,高20格)。用“-”号表示平面上的每个单元,用“*”号打印显示方块中的每个格子
	 * 
	 * @param tetromino 需要显示在游戏平面中的方块
	 */
	public static void printTetromino(Tetromino tetromino) {
		int totalRow = 20;
		int totalCol = 10;
		//获取方块中存储的四个各自的数组
		Cell[] cells = tetromino.cells;
		for (int row = 0; row < totalRow; row++) {
			for (int col = 0; col < totalCol; col++) {
				// 用于判断该位置是否包含在cells数组中
				boolean isInCells = false;
				for (int i = 0; i < cells.length; i++) {
					if (cells[i].row == row && cells[i].col == col) {
						System.out.print("* ");
						isInCells = true;
						break;
					}
				}
				if (!isInCells) {
					System.out.print("- ");
				}
			}
			System.out.println();
		}
	}
}

控制台输出结果如下所示:

--------打印T型---------
i am a T
(0,4), (0,5), (0,6), (1,5)
- - - - * * * - - - 
- - - - - * - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
--------打印J型---------
i am a J
(0,4), (0,5), (0,6), (1,6)
- - - - * * * - - - 
- - - - - - * - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - - 
- - - - - - - - - -

从以上输出结果可以看出,当把一个子类对象直接赋值给父类引用变量时,例如上面的代码:Tetromino t = new TetrominoT(0, 4);,这个t引用变量的编译时类型是Tetronimo,而运行时类型是TetrominoT。当运行时,如果子类覆盖了父类的某个方法8,那么,调用该引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,即,调用子类的方法。上边的代码运行后,输出了“i am a T”、“i am a J”也说明了调用了子类的print方法。

1.4 完整代码

本案例中,Tetromino类的完整代码如下所示:

public class Tetromino {
	Cell[] cells;// 属性,用来存储一个方块的四个格子的坐标

	/**
	 * 构造方法,初始化cells数组
	 */
	public Tetromino() {
		cells = new Cell[4];
	}
	/**
	 * 按顺时针方向,打印方块中四个格子所在的坐标
	 */
	public void print() {
		String str = "";
		for (int i = 0; i < cells.length - 1; i++) {
			str += "(" + cells[i].getCellInfo() + "), ";
		}
		str += "(" + cells[cells.length - 1].getCellInfo() + ")";
		System.out.println(str);

	}

	/**
	 * 使方块下落一个格子
	 */
	public void drop() {
		for (int i = 0; i < cells.length; i++) {
			cells[i].row++;
		}
	}

	/**
	 * 使方块左移一个格子
	 */
	public void moveLeft() {
		for (int i = 0; i < cells.length; i++) {
			cells[i].col--;
		}
	}

	/**
	 * 使用方块右移一个格子
	 */
	public void moveRight() {
		for (int i = 0; i < cells.length; i++) {
			cells[i].col++;
		}
	}
}

TetrominoT类的完整代码如下所示:

public class TetrominoT extends Tetromino {
	public TetrominoT(int row, int col) {
		super();
		// 按顺时针方向初始化Cell
		cells[0] = new Cell(row, col);
		cells[1] = new Cell(row, col + 1);
		cells[2] = new Cell(row, col + 2);
		cells[3] = new Cell(row + 1, col + 1);
	}

	@Override
	public void print() {
		System.out.println("i am a T");
		super.print();
	}
}

TetrominoJ类的完整代码如下所示:

public class TetrominoJ extends Tetromino {
	public TetrominoJ(int row, int col) {
		// 按顺时针方向初始化Cell
		cells[0] = new Cell(row, col);
		cells[1] = new Cell(row, col + 1);
		cells[2] = new Cell(row, col + 2);
		cells[3] = new Cell(row + 1, col + 2);
	}

	@Override
	public void print() {
		System.out.println("i am a J");
		super.print();
	}
}

TetrominoGame类的完整代码如下所示:

public class TetrominoGame {
	public static void main(String[] args) {
		//测试TetrominoT
		System.out.println("--------打印T型---------");
		Tetromino t = new TetrominoT(0, 4);
		t.print();
		printTetromino(t);
		
		//测试TetrominoJ
		System.out.println("--------打印J型---------");
		Tetromino j = new TetrominoJ(0, 4);
		j.print();
		printTetromino(j);
		
	}

	/**
	 * 打印出游戏所在的平面(宽10格,高20格)。用“-”号表示平面上的每个单元,用“*”号打印显示方块中的每个格子
	 * 
	 * @param tetromino 需要显示在游戏平面中的方块
	 */
	public static void printTetromino(Tetromino tetromino) {
		int totalRow = 20;
		int totalCol = 10;
		//获取方块中存储的四个各自的数组
		Cell[] cells = tetromino.cells;
		for (int row = 0; row < totalRow; row++) {
			for (int col = 0; col < totalCol; col++) {
				// 用于判断该位置是否包含在cells数组中
				boolean isInCells = false;
				for (int i = 0; i < cells.length; i++) {
					if (cells[i].row == row && cells[i].col == col) {
						System.out.print("* ");
						isInCells = true;
						break;
					}
				}
				if (!isInCells) {
					System.out.print("- ");
				}
			}
			System.out.println();
		}
	}
}