下面看一个简单的例子。”冒号打开幻灯片——
冒号和他的学生们(连载25)——软件应变(2)
时间:2011-07-03 BlogJava 郑晖
// 用直角坐标实现的复数类
public class Complex
{
private double x;
private double y;
public Complex(double x, double y)
{
this.x = x;
this.y = y;
}
public double real() { return x; }
public double imaginary() { return y; }
public double modulus() { return StrictMath.hypot(x, y); }
public double argument() { return StrictMath.atan2(y, x); }
public Complex add(Complex other)
{
return new Complex(x + other.x, y + other.y);
}
public Complex multiply(Complex other)
{
return new Complex(x * other.x - y * other.y,
x * other.y + y * other.x);
}
}
“这是一个用直角坐标实现的复数Java类,为简明起见,仅仅实现了实部、虚部、模、辐角、加法和乘法等运算。同样地,我们也可以用极坐标来实现。”冒号投影出另一段代码——
// 用极坐标实现的复数类
public class Complex
{
private double r;
private double theta;
public Complex(double x, double y)
{
r = StrictMath.hypot(x, y);
theta = StrictMath.atan2(y, x);
}
public double real() { return r * StrictMath.cos(theta); }
public double imaginary() { return r * StrictMath.sin(theta); }
public double modulus() { return r; }
public double argument() { return theta; }
public Complex add(Complex other)
{
return new Complex
(r * StrictMath.cos(theta) + other.r * StrictMath.cos(other.theta),
r * StrictMath.sin(theta) + other.r * StrictMath.sin(other.theta));
}
public Complex multiply(Complex other)
{
Complex product = new Complex(0, 0);
product.r = r * other.r;
product.theta = theta + other.theta;
return product;
}
}
冒号和他的学生们(连载25)——软件应变(3)
时间:2011-07-03 BlogJava 郑晖
句号似已深明其意:“这两个类的接口相同而实现方式不同,它们的区别是结构性的,而不是功能性的。就实现效率而论,直角坐标便于加减运算,而极坐标便于乘除、乘方开方等运算。实现者可能会为采用何种方案而举棋不定,好在由于隐藏了结构性信息,即使以后修改了实现方案,也不会影响客户。”
冒号补充道:“如果将代码移植到C++,修改了实现方案,还是可能在一定程度上影响客户的。”
叹号有些惊讶:“为什么?C++不也是OOP语言吗?”
冒号解释:“由于C++需要头文件,即使私有成员也必须在头文件中声明。这意味着改动任何私有数据结构甚至私有方法的签名,所有包含该头文件的源代码虽不必改写,却需要重新编译链接。这对大型程序来说通常是难以忍受的,同时也说明设计与语言息息相关的。如果一个设计者只是高高在上,完全不考虑语言细节,难免流于纸上谈兵。”
逗号问道:“为什么Java不需要头文件呢?”
“因为Java、C#包括D语言中类似头文件的信息,已经在编译时自动提取并保存了。”冒号道出缘由,“出于历史原因和效率上的考虑,C++仍沿用C的头文件用法,成为除指针和内存管理之外 |