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 +
?
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))
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.
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))