Scala: surcharge de la méthodede l'opérateur

L'exemple suivant est tiré du livre "Programmation Scala". Étant donné une classe "rationnelle" et la définition de la méthode suivante:

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

je peux avec succès surcharger la méthode add avec une version de commodité qui prend un argument Int, et fait usage de la définition au-dessus de :

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

Aucun problème jusqu'à présent.

maintenant, si je change le nom de la méthode en un nom de style d'opérateur:

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

Et de la surcharge de la sorte:

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

, j'obtiens l'erreur de compilation suivante:

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

pourquoi le compilateur recherche-t-il une version unaire de la méthode + ?

33
demandé sur Peter Mortensen 2010-01-02 13:51:20

3 réponses

à Scala, toute construction du type +x , -x , ~x et !x est transformé en appel de méthode x.unary_+ , etc. Ceci est en partie pour permettre la syntaxe Java d'avoir !b comme négation du booléen b , ou -x comme négation du nombre x .

par conséquent, l'extrait de code +(new Rational(that, 1)) est traduit en (new Rational(that,1)).unary_+ , et comme Rational n'a pas cette méthode, vous obtiendrez une erreur de compilation. Vous obtiendrez cette erreur seulement si votre fonction est appelée + , - , ~ ou ! car ce sont les seuls caractères que Scala autorise en tant qu'opérateurs unaires. Par exemple, si vous avez appelé votre fonction @+ , le code se compile très bien.

cependant, je suggérerais d'écrire la fonction d'ajout surchargée comme:

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

Ce code montre l'intention de votre fonction-vous ajouter un nouveau Rational construit à partir d'un entier comme numérateur et 1 comme dénominateur à this . Cette façon d'écrire est traduite en this.+(new Rational(that, 1)) , ce qui est ce que vous voulez -- en invoquant la fonction + sur this .

Notez que vous pouvez utiliser la notation infixe cependant que la fonction est appelée. Par exemple, si vous modifiez le nom de add , vous pouvez toujours garder la définition:

def add(that: Int): Rational =
  this add (new Rational(that, 1))
51
répondu Flaviu Cipcigan 2014-01-13 16:17:50

si vous appelez + avec this explicite, ça devrait marcher

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

Scala permet de définir des opérateurs unaires qui peuvent être utilisés dans la notation de l'opérateur de préfixe. Par exemple, vous pouvez utiliser + comme opérateur de préfixe pour obtenir le même résultat:

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

Sans alternative this dans votre exemple, le compilateur que vous utilisez l'opérateur unaire + qui n'est pas définie.

6
répondu Mushtaq Ahmed 2016-05-29 21:01:03

vous n'avez pas spécifié l'opérateur binaire+, vous avez spécifié l'opérateur unary+.

donc au lieu de:

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

vous devez écrire ceci:

def +(that: Int): Rational =
  this +(new Rational(that, 1))
3
répondu kikibobo 2010-01-02 11:37:04