In Scala I can do this:
trait SomeTrait {
protected def foo: String
}
class Wibble extends SomeTrait {
protected var foo = "Hello"
}
But I cannot do the same thing where I provide a default definition for foo
trait SomeTrait {
protected def foo: String = "World"
}
class Wibble extends SomeTrait {
protected var foo = "Hello" //complains about lack of override modifier
override protected var foo = "Hello" //complains "method foo_ overrides nothing"
}
Why can't I do this?
EDIT: After a conversation on the scala-users mailing list, I have raised this in trac
Scala overriding method provides your own implementation of it. When a class inherits from another, it may want to modify the definition for a method of the superclass or provide a new version of it. This is the concept of Scala method overriding and we use the 'override' modifier to implement this.
In Scala, method overriding uses override modifier in order to override a method defined in the super class whereas, method overloading does not requires any keyword or modifier, we just need to change, the order of the parameters used or the number of the parameters of the method or the data types of the parameters ...
In Scala, when you write a var foo
, the Scala compiler automatically generates a setter (called foo_=
) and a getter (called foo
) for it, and sets the field as private (you'll see it as private if you decompile a class having 'public' Scala fields with javap
). That's what the 'method foo_= overrides nothing' error means. In your trait you haven't defined a foo_=
method, and for a public field setter and getters always come in pairs.
If you do not provide a default value in the trait (i.e. abstract method), then the override
keyword is not necessary. Therefore, in your first example, the getter overrides the abstract method and the setter... it just is there. The compiler doesn't complain. But when you provide an actual implementation of the method in the trait, you need to specifically write the override
keyword when overriding. When writing protected var foo
, you haven't specified the override
keyword for the getter and when writing override protected var foo
, you have also indicated to the compiler that method foo_=
is to be overridden, but the trait has no such method.
Also, logically you cannot really override a def
with a var
(considering a strict view of overriding, like in the previous paragraph). A def
is logically a function (you give it some input, it produces an output). A var
is similar to a no-arg function, but also supports setting its value to something else, an operation which is not supported by a function. Instead, if you would change it to a val
, it would be OK. It's like a function that always produces the same (cached) result.
If you want to have similar behaviour to a var
you could do something like this (by having explicit setter and getters):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Now you can do anything you could do with a var :).
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With