为什么不能使用隐式转换来减少需要定义的方法的数量?

时间:2014-02-02 03:26:03

标签: scala implicit-conversion

这是Oderdki教授的名为Rational的示例类,简化为强调:

class Rational(n: Int, d: Int) {
    def + (that: Rational): Rational =
        new Rational(this.numer * that.denom + that.numer * this.denom, 
                     this.denom * that.denom)
    def + (that: Int): Rational = 
        new Rational(this.numer + that * this.denom, this.denom)
     

// implicit def IntToRational(a:Int)= new Rational(a)}

它不适用于表达式:

1 + new Rational(1, 2)

除非我取消注释隐式函数intToRational,它允许Scala自动转换l.h.s.到理性。 我的问题是:如果我必须定义一个转换函数来处理Int在lhs上的时候,为什么我必须定义一个在rhs上出现时需要Ints的方法?

以另一种方式提出问题,为什么Scala编译器不能将Int参数转换为Rational,所以我的第一个'+'定义(它接受一个Rational参数)适用于两者案件?

在我看来,Scala是一种如此聪明的语言,可能有一种方法可以声明一个类在其方法中是“可交换的”,因此编译器可以自由地进行这样的替换。然后,表达式:

Rational(1, 2) + 1

1 + Rational(1, 2)

两者都以相同的方式处理,并采用相同的方法。

我认为这是难以回答的问题之一,因为根据您的要求,答案要么非常明显,要么非常微妙。我认为这是一个值得解决的问题。顺便说一句,我喜欢Oderski教授在Coursera上课的课程!

1 个答案:

答案 0 :(得分:2)

可以在双方使用Implicits,但是以效率为代价:添加Int是一种更简单的操作。

通常你会像这样关心基本数学的效率。

正因为如此,你通常不会为LHS编写intToRational,而是

implicit class IntRationalOps(val i: Int) extends AnyVal {
  def +(r: Rational) = r + i
}

如果效率不是那么重要且可以始终执行转换(对于数学或其他事情),则隐式可以提供帮助。 (如果在任何地方转换都不是一个好主意,仍然可以使用IntRationalOps方法。)