En Scala, lorsque vous écrivez un var foo
, le compilateur Scala génère automatiquement un setter (appelé foo_=
) et un getter (appelé foo
) et définit le champ comme privé (vous le verrez comme privé si vous décompilez une classe ayant des champs Scala 'publics' avec javap
). C'est ce que signifie l'erreur 'method foo_ = overrides nothing'. Dans votre trait, vous n'avez pas défini une méthode foo_=
, et pour un accesseur de champ public et des getters toujours viennent par paires.
Si vous ne fournissez pas de valeur par défaut dans le trait (c'est-à-dire la méthode abstraite), le mot-clé override
n'est pas nécessaire. Par conséquent, dans votre premier exemple, le getter remplace la méthode abstraite et le setter ... il est juste là. Le compilateur ne se plaint pas. Mais lorsque vous fournissez une implémentation réelle de la méthode dans le trait, vous devez écrire spécifiquement le mot-clé override
lors du remplacement. Lorsque vous écrivez protected var foo
, vous n'avez pas spécifié le mot-clé override
pour le getter et lorsque vous écrivez override protected var foo
, vous avez également indiqué au compilateur que la méthode foo_=
doit être remplacée, mais le trait n'a pas cette méthode.
Aussi, logiquement, vous ne pouvez pas vraiment surcharger un def
avec un var
(en considérant une vue stricte de dérogation, comme dans le paragraphe précédent). Une def
est logiquement une fonction (vous lui donnez une entrée, elle produit une sortie). Un var
est similaire à une fonction sans argument, mais prend également en charge la définition de sa valeur à autre chose, opération qui n'est pas prise en charge par une fonction. Au lieu de cela, si vous le changez en val
, ce serait OK. C'est comme une fonction qui produit toujours le même résultat (en cache).
Si vous voulez avoir un comportement similaire à un var
que vous pourriez faire quelque chose comme ça (en ayant setter explicite et getters):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Maintenant, vous pouvez faire tout ce que vous pourriez faire avec un :) var.
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"
Désolé - j'ai fait une erreur - la méthode trait originale aurait dû être protégée aussi. Je ne suis pas sûr d'être d'accord avec vous sur l'impossibilité logique de remplacer un 'def' par un' var'. Tout ce que 'def' dit est que je m'attends à ce qu'il y ait un accesseur appelé' foo' qui retourne une chaîne - déclarant un 'var' est une implémentation de ceci –
Je pense que je suis d'accord avec vous. Je pensais à dépasser comme une notion plus stricte quand j'ai écrit la réponse. Je vais éditer la réponse, et fournir une solution réalisable :). –
Dommage qu'il n'y ait pas de syntaxe 'override def as var ' –