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
  )
x
 
#<undef>

=======

启发

在面向对象编程的世界里呆久了,似乎构造函数一定需要构造出一个“坚固”的对象,即有明确属性的对象。比如一个复数类,一定会想着用一个属性去存储其实部,用另一个属性去存储其虚部。就算再添加几个方式,用来分别获取模和幅角,也一定是用 this.xthis.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);
 
1
2
2.23606797749979
1.1071487177940904
undefined

然而,通过闭包,可以不用在对象里存储具体的属性值,从而变成所谓的“智能数据对象”。虽然没有在一个“对象”中存储具体的值,但通过提供相应的方法,实现的效果也是一样的。

 
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'));
 
1
2
2.23606797749979
1.1071487177940904
undefined

results matching ""

    No results matching ""