Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Accessing protected field of companion object's trait

Tags:

scala

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?

like image 239
bwroga Avatar asked Dec 04 '12 23:12

bwroga


2 Answers

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.

like image 21
Dominic Bou-Samra Avatar answered Oct 04 '22 13:10

Dominic Bou-Samra


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
}
like image 145
som-snytt Avatar answered Oct 04 '22 13:10

som-snytt