我想编写一个可以很好地处理数字和运算符的类,所以我想知道当左手参数是内置类型或其他值时,如何重载运算符,我不能这样做修改实施。
class Complex(val r:Double,val i:Double){
def +(other:Complex) = new Complex(r+other.r,i+other.i)
def +(other:Double) = new Complex(r+other,i)
def ==(other:Complex) = r==other.r && i==other.i
}
通过这个例子,以下工作:
val c = new Complex(3,4)
c+2 == new Complex(5,4) //true
但我也希望能够写
2+c
不能正常工作Int.+
无法接受Complex
类型的参数。
有没有办法让我写这个并让它按我的意愿工作?
我发现了正确的关联方法,但它们似乎需要不同的运营商名称。
答案 0 :(得分:6)
您可以添加从Int到Complex的隐式转换:
implicit def intToComplex(real: Int) = new Complex(real, 0)
您可以阅读有关含义的信息(例如:Understanding implicit in Scala)。简短的版本是,如果你的程序没有进行类型检查,那么将尝试当前作用域中的所有含义,如果其中一些有效,它将由编译器应用。
因此,当您编写2 + c
时,编译器找不到在Int中使用复数的运算符+,因此它会尝试隐含。然后它会将2 + c
编译为intToComplex(2) + c
,这将正常工作。
答案 1 :(得分:3)
如前所述,使用隐式转化将Int
转换为Complex
即可完成此任务。
这是一个有效的解决方案,它将所有这些放在一起,以补充伊万的答案:
import scala.language.implicitConversions
class Complex(val real:Double, val imaginary:Double){
def +(other:Complex) = new Complex(real+other.real, imaginary+other.imaginary)
//def +(other:Double) = new Complex(real+other,imaginary) // Not needed now
def ==(other:Complex) = real==other.real && imaginary==other.imaginary
override def toString: String = s"$real + ${imaginary}i"
}
object Complex {
implicit def intToComplex(real: Int): Complex = doubleToComplex(real.toDouble)
implicit def doubleToComplex(real: Double): Complex = Complex(real, 0)
implicit def apply(real: Double, imaginary: Double): Complex = new Complex(real, imaginary)
implicit def apply(tuple: (Double, Double)): Complex = Complex(tuple._1, tuple._2)
def main(args: Array[String]) {
val c1 = Complex(1, 2)
println(s"c1: $c1")
val c2: Complex = (3.4, 4.2) // Implicitly convert a 2-tuple
println(s"c2: $c2")
val c3 = 2 + c1
println(s"c3: $c3")
val c4 = c1 + 2 // The 2 is implicitly converted then complex addition is used
println(s"c4: $c4")
}
}
一些注意事项:
Int
输入(因此我将其注释掉了)。示例c4
证明了这一点。 Double
,只需使用一些足以满足您需求的数字类型。复数的概念实际上与它扩展的字段/环/组完全分离。例如,如果您的基础类型具有乘法和加法,您也可以为复数定义乘法和加法。Tuple2[Double, Double]
类添加了一个隐式转换 - 只是因为它看起来很酷。示例c2
演示了它。apply
个方法。请考虑添加unapply
方法,使其更加case
友好。toString
方法不那么混乱(所以你没有$ {i} i)==
方法正在比较类型Double
,而不是Int
,因此您将获得所有通常的挫折和浮点比较的意外行为答案 2 :(得分:-1)
运算符的关联性由运算符的最后一个字符决定。以冒号结尾的运算符':'是正确联想的。所有其他运算符都是左关联的。
所以你最接近的是2 +: c