Разрешить рациональному классу обрабатывать математические операторы


У меня есть этот рациональный класс, который имеет метод для каждой операции (add, mult и т. д.)

function Rational(nominator, denominator){
    this.nominator = nominator;
    this.denominator = denominator || 1;    
}

Rational.prototype = {
    mult: function(that) {
        return new Rational(
            this.nominator * that.nominator,
            this.denominator * that.denominator
            );
    },
    print: function() {
        return this.nominator + '/' + this.denominator;
    }
};

var a = new Rational(1,2),
    b = new Rational(3);

console.log( a.mult(b).print() ); // 3/2

Могу ли я сделать его более "естественным", например, включить console.log( a * b ) ?

3 5

3 ответа:

Нельзя перегружать операторы (читайте аналогичные вопросы ).

Более того, выделенный метод, подобный mult, может рассматриваться как признак хорошего дизайна (не только в Javascript), поскольку изменение исходного поведения оператора может запутать пользователей (ну, рациональное число на самом деле хороший кандидат для перегрузки).

Вы можете изменить print на toString, как предложил пользователь thg435.

Идем еще дальше:

Rational.prototype = {
    mult : ... ,
    toString: ... ,
    valueOf: function() { return this.nominator / this.denominator; }
};

Это позволит a * b синтаксис (Примечание: Вы больше не работаете с Rationals, а скорее с примитивами).

Самое близкое, что вы можете получить, - это своего рода псевдоним оператора, например:

/* Accepts a symbolic or string operator, returns a function which accepts numbers */
function operator(node)
  {
  //Mapping between string and symbol operators
  var map = {"mod": "%", "mult": "*", "div": "/", "plus": "+", "minus": "-"}

  //Return a function which applies the string or symbol operator to two numbers
  return Function("x,y", "return x" + (map[node] || node) + "y");
  }

// pass "*" to operator; pass 5,7 to returned function
var foo = operator("*")(5,7); 

// pass "plus" to operator; pass 3,2 to returned function
var bar = operator("plus")(3,2);

// pass "mod" to operator; pass 1,0 to returned function 
var baz = operator("mod")(1,0); 

console.log(["foo",foo,"bar",bar,"baz",baz]); //["foo", 35, "bar", 5, "baz", NaN]

Ссылки

В качестве идеи вы можете попробовать написать парсер самостоятельно, чтобы написать что-то вроде этого:

console.log(R("a * b")); 

Где R-функция, которая преобразует a * b В a. mult(b), а затем вычисляет это.