2.75
练习 2.75 请用消息传递的风格实现构造函数make-from-mag-ang
。这一过程应该与上面给出的make-from-real-imag
过程类似。
(define (make-from-mag-ang mag ang)
(define (dispatch op)
(cond
((eq? op 'real-part) (* mag (cos ang)))
((eq? op 'imag-part) (* mag (sin ang)))
((eq? op 'magnitude) mag)
((eq? op 'angle) ang)
(else
(error "Unknown op -- MAKE-FROM-MAG-ANG" op)
)
)
)
dispatch
)
=======
启发
在面向对象编程的世界里呆久了,似乎构造函数一定需要构造出一个“坚固”的对象,即有明确属性的对象。比如一个复数类,一定会想着用一个属性去存储其实部,用另一个属性去存储其虚部。就算再添加几个方式,用来分别获取模和幅角,也一定是用 this.x
和 this.y
来进行计算。
即大致是这样的代码:
class ComplexNumber {
constructor(x, y) {
this.x = x;
this.y = y;
this.mag = Math.sqrt(this.x * this.x + this.y * this.y);
this.ang = Math.atan(y, x);
}
static fromMagAng(mag, ang) {
const x = mag * Math.cos(ang);
const y = mag * Math.sin(ang);
const c = new ComplexNumber(x, y);
c.mag = mag;
c.ang = ang;
return c;
}
get realPart() {
return this.x;
}
get imagPart() {
return this.y;
}
get magnitude() {
return this.mag;
}
get angle() {
return this.ang;
}
}
const c = new ComplexNumber(1, 2);
console.log(c.realPart);
console.log(c.imagPart);
console.log(c.magnitude);
console.log(c.angle);
然而,通过闭包,可以不用在对象里存储具体的属性值,从而变成所谓的“智能数据对象”。虽然没有在一个“对象”中存储具体的值,但通过提供相应的方法,实现的效果也是一样的。
const makeComplexNumberFromRealImag = (x, y) => {
const dispatch = (op) => {
switch (op) {
case 'realPart':
return x;
case 'imagPart':
return y;
case 'magnitude':
return Math.sqrt(x * x + y * y);
case 'angle':
return Math.atan(y / x);
default:
throw new Error('Unknown op: ' + op);
}
}
return dispatch;
};
const n = makeComplexNumberFromRealImag(1, 2);
console.log(n('realPart'));
console.log(n('imagPart'));
console.log(n('magnitude'));
console.log(n('angle'));