I have a Trait, a Companion Object and a Class in Scala:
trait A {
protected var foo = "Foo"
}
object B extends A {
}
class B {
println(B.foo)
}
Why can't I access foo? I thought that foo would become a field of the object "B". Is there a way to do this?
Scala by default uses public fields. It also has private and protected. Private modifiers work the same as Java, but protected, works dramatically different.
The first difference is that protected can have two forms: protected
and protected[bar]
. Where bar
can be a class, package or object.
From the Scala language spec:
A protected identifier x may be used as a member name in a selection r .x only if one of the following applies:
– The access is within the template defining the member, or, if a qualification C is given, inside the package C, or the class C, or its companion module, or
– r is one of the reserved words this and super, or
– r ’s type conforms to a type-instance of the class which contains the access.
In other words, the non-parameterized protected field is only visible from subclasses not from the same package.
The spec says you can access protected members from:
the companion module of any of those classes [that have the defining template as a base].
That is, not from the companion class of an object that has the defining template as a base. Tricky.
This is not obvious because of the "module" nomenclature, where module simply means object. There is occasional talk about changing that. Although classes and modules can be companions, the relation is not symmetric; consider implicit search.
trait A {
protected var foo = "Foo"
protected def bar = "Bar"
}
object B extends A {
//override protected var foo = super.foo // no
override protected def bar = super.bar
}
class B {
//println(B.foo) // no
println(B.bar) // ok
}
class C extends A
object C {
println(new C().foo) // ok
}
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