1 泛值
明显有很大的重复以及各种硬编码(hard code):
public void saveStudentA() {
// TODO pseudo code
// insert A into table Student
}
public void saveStudentB() {
// TODO pseudo code
// insert B into table Student
}
所谓的“泛”,就是特殊到一般的过程,或者说是具体到抽象的过程:
public void saveStudent(Student xxx) {
// TODO pseudo code
// insert xxx into table Student
}
2 泛型(generic type)
假如你和你一个同事在开发一套系统,你负责“学生模块”,你有一个 saveStudent方法;你的同事负责“教师模块”,他有一个 saveTeacher 方法。
public void saveTeacher(Teacher xxx) {
// TODO pseudo code
// insert xxx into table Teacher
}
2.1 泛型方法
减少因类型不同而产生的重复.
public void save (XXX xxx) {
// TODO pseudo code
// insert xxx into table XXX
}
2.2 泛型类
Comparable
3 泛函
高斯的求和
/** 求普通和 */
public static int sum() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
更多的求和
现在,让我们来看更多的求和问题,除了普通的求和,我们还可能想求比如平方和,那么可以这样写:
/** 求平方和 */
public static int sum() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i * i;
}
return sum;
}
如果想求立方和,可以这样写:
/** 求立方和 */
public static int sum() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i * i * i;
}
return sum;
}
泛函的解决方案(lambda 式)
import java.util.function.Function;
public class LamdbaFunctionalDemo {
public static void main(String[] args) {
int idSum = sum(integer -> integer);
int sqSum = sum(integer -> integer*integer);
int cuSum = sum(integer -> integer*integer*integer);
double sqSum2 = sumf(i -> Math.pow(i, 2));
double cbSum2 = sumf(i -> Math.pow(i, 3));
}
public static int sum(Function f) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += f.apply(i);
}
return sum;
}
public static double sumf(Function f) {
double sum = 0;
for (int i = 1; i <= 100; i++) {
sum += f.apply((double) i);
}
return sum;
}
}
所谓的“泛”
现在,我们来看所谓的“泛”,前面的篇章中也一再说了,就是一个从特殊到一般的过程:
是一个从具体到抽象的过程:
函数已经是一种抽象,我们还不满足,我们还要追求更高阶的抽象:
还是那句话,从特殊到一般,从一般到更一般!无论是值的硬编码、类型的硬编码,还是行为的硬编码,能够被泛化的,我们都将其一一参数化,一般化。
在这一过程中,我们消除了重复,得到了极为抽象的代码,这些对值没有依赖,对类型也没有依赖,对具体行为也没有耦合的代码具有极强的普适性。依靠这些手段,我们不但消除了眼下的重复,甚至也消除了未来的重复。
当你写的代码越来越多,当你思考得越来越深,你一定对这一点体会越来越深。或许我们还不能将它清晰的表述出来,但我相信我们一定会逐渐地感受到,用陶潜的一句诗来结尾,可谓是:此中有真意,欲辨已忘言!