【问题标题】:Enable a Rational class to handle math operators启用 Rational 类来处理数学运算符
【发布时间】:2013-06-11 01:38:33
【问题描述】:

我有这个 Rational 类,每个操作都有一个方法(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 ) ?

【问题讨论】:

  • Javascript 不支持运算符重载。不过,您可以将 print() 替换为 toString
  • 可以使用某种形式的 eval 和字符串替换,例如:console.log( Function("a * b".replace(" * b",".mult(b).print() " ) ) ) 有关于宏的onetwo 问题可能会有所帮助。

标签: javascript operator-overloading dsl prototypal-inheritance fractions


【解决方案1】:

您不能重载运算符(阅读similar questions)。

此外,像mult 这样的专用方法可以被视为良好设计的标志(不仅在 Javascript 中),因为更改 original 操作符的行为会使用户感到困惑(嗯,一个有理数实际上是重载的好候选)。

您可以按照用户 thg435 的建议将 print 更改为 toString

更进一步:

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

这将启用a * b 语法(注意:您不再对Rationals 进行操作,而是对原语进行操作)。

【讨论】:

  • 我也是这么想的,结果发现错了:试试new Rational(1,3).toString()
  • 不,它没有。如果您定义 valueOf,字符串转换将使用它,而不是您的 toString。所以你得到0.3333 而不是1/3
  • 我已经向question 专门询问过这个问题。
  • @thg435 啊,现在我明白你的意思了。是的,当valueOf 将返回一个原语时,toString 可能不会被调用,因此0.3333。但是toString(在我的回答中)的情况是在显式调用中替换print
【解决方案2】:

作为一个想法,您可以尝试自己编写一个解析器,这样您就可以编写如下内容:

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

其中 R 是将 a * b 转换为 a.mult(b) 然后 eval 的 this 的函数。

【讨论】:

    【解决方案3】:

    您可以获得的最接近的是某种运算符别名,例如:

    /* 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]
    

    参考文献

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多