15

I have the following code:

class Base{
    protected val alpha ="Alpha";
    protected def sayHello = "Hello";
}
class Derived extends Base{
        val base = new Base;
        def hello = println(this.alpha +" "+this.sayHello) ;
       // def hello = println(base.alpha +" "+base.sayHello) ; // don't compile
    }

    object MyObj extends App{
            val x=new Derived;
            x.hello;
        }

In class Base, if I label protected with this, the code works as expected; if I don't label it with this, everything works as expected too.

Are protected and protected[this] equivalent in Scala? If yes, why would Scala provide both? If not, how do they differ?

jub0bs
  • 60,866
  • 25
  • 183
  • 186
optional
  • 3,260
  • 5
  • 26
  • 47

2 Answers2

22

Scala protected and its siblings protected[this] , protected[pkg] is somewhat overwhelming ,However I found easy to remember solution by using the Java philosophy of protected . 1st How protected member is visible to in Java

  1. They are visible to subclass(subclass may be in same package or other package)
  2. They are visible to any class that is in same package as class that specified protected member.

Obviously they are visible to class itself.

But Scala has some restriction on how they are visible to subclass.By default,They are visible to subclass only . They are not visible to package in which class is declared .However two case exist how they are visible in subclass .

if protected member is not qualified(plain protected) then it is visible with another instances of declaring class into declaring class as well as with this into class and subclass e.g

class Base{
    protected val alpha ="Alpha";
    protected def sayHello = "Hello";
}
class Derived extends Base{
        def hello = println((new Derived()).sayHello) ;
        def hello2 = println(this.sayHello);

}

if protected member is qualified with this .It is only accessible with this in class and subclass ,It can't be accessed by other instances of declaring class or subclass e.g.

class Base{
    protected val alpha ="Alpha";
    protected[this] def sayHello = "Hello";
    def foo = Console println(new Base().sayHello) // won't compile
    def bar = Console println(this.sayHello)
}
class Derived extends Base{
        def hello = println(this.sayHello) ;
        //def hello2 = println((new Derived() .sayHello) // won't compile
}

Since Scala do not support the package level access of protected member by default .but if you want to make it available at package level then you need to specify package explicitly e.g. protected[pkg]. Now this protected member is visible with declaring class/Subclass instances if they are accessed in classes declared in pkg or below.

e.g.

package com.test.alpha{
class Base{
    protected val alpha ="Alpha";
    protected[test] def sayHello = "Hello"; // if you remove [test] it won't compile
}

class Derived extends Base{
    val base = new Base
        def hello = println(base.sayHello) ;
}}

This is how one can remember Scala protected

optional
  • 3,260
  • 5
  • 26
  • 47
2

The difference is that with protected[this] the subclass instance can only access its own fields (this.x), whereas with protected the subclass can access the fields in all instances (not only in this):

class Base{
  protected val alpha ="Alpha";
  protected[this] def sayHello = "Hello";
}

class Derived extends Base{
  def hello = println(this.alpha +" "+this.sayHello) ;
  def hello2 = println(
   new Derived().alpha +" "
   +new Derived().sayHello) ; // error on "sayHello"
}

In this code, you can access this.sayHello, but not other.sayHello. The protected alpha does not have this restriction.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • what you mean that I can access `base.alpha` in `Derived` – optional Apr 28 '16 at 07:54
  • I tried it as you asked but same result ,I am using Scala 2.11.7 – optional Apr 28 '16 at 08:05
  • **ProtectedDemo.scala:7: error: value alpha in class Base cannot be accessed in Base Access to protected value alpha not permitted because prefix type Base does not conform to class Derived where the access take place def hello = println(base.alpha) ;** – optional Apr 28 '16 at 08:09
  • 1
    Yes exactly , Member that as qualified with `[this]` only accessible with `this` qualifier . and If I need to access `alpha` with `Base` instance than I need to qualify it with `protected[pkg_of_scbclass]` ,Right ? – optional Apr 28 '16 at 08:26