2010-01-02 38 views
33

El siguiente ejemplo es del libro 'Programación en Scala'. Dada una clase de 'racional' y la siguiente definición del método:Scala: método sobrecarga del operador

def add(that: Rational): Rational = 
    new Rational(
     this.numer * that.denom + that.numer * this.denom, 
     this.denom * that.denom 
    ) 

puedo sobrecargar con éxito el método add con una versión de conveniencia que toma un argumento int y hace uso de la definición anterior:

def add(that: Int): Rational = 
    add(new Rational(that, 1)) 

Sin problemas hasta el momento.

Ahora, si cambio el nombre del método a un nombre de estilo operador:

def +(that: Rational): Rational = 
    new Rational(
     this.numer * that.denom + that.numer * this.denom, 
     this.denom * that.denom 
    ) 

y la sobrecarga de este modo:

def +(that: Int): Rational = 
    +(new Rational(that, 1)) 

me sale el siguiente error de compilación:

(fragment of Rational.scala):19: error: value unary_+ is not a member of this.Rational 
+(new Rational(that, 1)) 
^ 

¿Por qué el compilador busca una versión única del método +?

Respuesta

50

En Scala, cualquier construcción del tipo +x, -x, ~x y !x se transforma en una llamada de método x.unary_+, etc. Esto es parcialmente para permitir la sintaxis de Java-como de tener !b como la negación de la boolean b, o -x como la negación del número x.

Por lo tanto, el fragmento de código +(new Rational(that, 1)) se traduce en (new Rational(that,1)).unary_+, y como Rational no tiene este método, se obtiene un error de compilación. Obtendrá este error solo si su función se llama +, -, ~ o ! ya que estos son los únicos caracteres que Scala permite como operadores unarios. Por ejemplo, si llamó a su función @+, el código se compila muy bien.

Aunque, sugeriría escribir la función de complemento reemplazado como:

def +(that: Int): Rational = 
    this + (new Rational(that, 1)) 

Este código muestra el intento de su mejor función - se agrega una nueva Rational construido a partir de un entero como un numerador y denominador 1 a this. Esta forma de escribir se traduce a this.+(new Rational(that, 1)), que es lo que desea - invocando la función + en this.

Tenga en cuenta que puede utilizar la notación infija, pero se llama a la función. Por ejemplo, si cambia el nombre de nuevo a add, todavía se puede mantener la definición como:

def add(that: Int): Rational = 
    this add (new Rational(that, 1)) 
3

No ha especificado el operador binario +, que ha especificado el operador unario +.

Así que en lugar de:

def +(that: Int): Rational = 
    +(new Rational(that, 1)) 

Usted tiene que escribir esto:

def +(that: Int): Rational = 
    this +(new Rational(that, 1)) 
5

Si llama + con explícita this, debería funcionar

def +(that: Int): Rational = this.+(new Rational(that, 1)) 

Scala permite definir operadores unarios que se pueden usar en notación de operador de prefijo. Por ejemplo, puede utilizar + como un operador de prefijo para lograr el mismo:

def unary_+: Rational = this.+(new Rational(that, 1)) 
val a = new Rational(3,2) 
val b = +a 

Sin explícita this en su ejemplo, el compilador piensa que está utilizando operador unitario + que no se define.