7.4 再谈泛化

前面的 printTable 版本总是显示 6 行,我们可对其进行泛化,用形参替换字面量 6

  1. public static void printTable(int rows) {
  2. int i = 1;
  3. while (i <= rows) {
  4. printRow(i);
  5. i = i + 1;
  6. }
  7. }

下面是用实参 7 调用这个方法得到的输出:

  1. 1 2 3 4 5 6
  2. 2 4 6 8 10 12
  3. 3 6 9 12 15 18
  4. 4 8 12 16 20 24
  5. 5 10 15 20 25 30
  6. 6 12 18 24 30 36
  7. 7 14 21 28 35 42

这个版本更好,但还存在一个问题:每次显示的列数相同。要想进一步泛化,可给 printRow 再添加一个形参:

  1. public static void printRow(int n, int cols) {
  2. int i = 1;
  3. while (i <= cols) {
  4. System.out.printf("%4d", n * i);
  5. i = i + 1;
  6. }
  7. System.out.println();
  8. }

现在 printRow 接受两个形参——ncolsn 指定要计算哪个值的整数倍,而 cols 指定列数。因为我们给 printRow 添加了一个形参,所以还需要修改 printTable 中调用 printRow 的代码行:

  1. public static void printTable(int rows) {
  2. int i = 1;
  3. while (i <= rows) {
  4. printRow(i, rows);
  5. i = i + 1;
  6. }
  7. }

这行代码执行时会将 rows(这里为 7)作为实参传递给 printRow。在 printRow 中,这个值被赋给 cols,这导致列数等于行数,因此得到的是一个 7×7 的方形表格:

  1. 1 2 3 4 5 6 7
  2. 2 4 6 8 10 12 14
  3. 3 6 9 12 15 18 21
  4. 4 8 12 16 20 24 28
  5. 5 10 15 20 25 30 35
  6. 6 12 18 24 30 36 42
  7. 7 14 21 28 35 42 49

合理地泛化方法常常会得到计划外的功能。例如,你可能注意到了,前面的乘法表是对称的,这是因为 ab=ba,所以这个表格中的每项都出现了两次。为节省油墨,可只打印这个表格的一半,为此只需要修改 printTable 中的一行代码:

  1. printRow(i, i);

这使得每行的长度与其行号相同,结果是一个三角形乘法表:

  1. 1
  2. 2 4
  3. 3 6 9
  4. 4 8 12 16
  5. 5 10 15 20 25
  6. 6 12 18 24 30 36
  7. 7 14 21 28 35 42 49

泛化可让代码更通用、更易于重用甚至更容易编写。