What does passing [this] after access modifier mean?


#1

I noticed this kind of statements/function definitions in scala

private[this] def sizeInternal(cur: ListMap[K, V1], acc: Int): Int = ???

Why is there “[this]” after private? And what does it mean? Where else can this be used (in class definitions too?)?


#2

You can adapt the scope of access modifiers with [...].

In this example, x will be private within the package foo, instead of within class Baz only. And y will only be accessible for everything within object bar.

package foo {
  object bar {
    class Baz { 
      private[foo] def x = ??? 
      private[bar] def y = ???
    }
  }
}

private[this] works the same way. It means that your method sizeInternal will only be accessible by the current instance. Which basically means you can only call that method on this, either implicitly or explicitly.

scala> class Foo { private def foo(f: Foo): Nothing = f.foo(this) }
defined class Foo

scala> class Foo { private[this] def foo(f: Foo): Nothing = f.foo(this) }
                                                              ^
       error: value foo is not a member of Foo

scala> class Foo { private[this] def foo(f: Foo): Nothing = foo(f) }
defined class Foo

#3

Thank you:)


#4

IIRC private[this] is also used to change the access modifier in Java bytecode, i.e. private in Scala doesn’t translate to private in bytecode, only private[this] does. JVM JIT optimizes for private methods quicker and more reliably than for non-private ones (because global analysis is not required), thus attaching [this] to broadly and frequently used private methods should improve performance.

Feel free to correct me if I’m wrong :slight_smile:


#5

Normal unqualified private gets translated to bytecode private most of the time. As far as I know only in these cases gets a private method compiled to a public method:

  • a private method in a class/trait that gets called from the companion object,
  • a private method in an object that gets called from the companion class/trait.

There might be some other corner cases I’m missing. But I believe that private[somePackageOrObject] always translates to public.

Something that might have a performance impact (though I think the JIT should be pretty good at eliminating this anyway), is that a private[this] val gets compiled to a field only. While private val gets compiled to a field and an accessor method.


#6
class OuterA {

    class InnerA {
      private[OuterA] def getFoo: String = "Foo"
    }

  }

private[OuterClass] def getFoo : String is same as public def getFoo : String ??


#7

No. For all Scala programs private[OuterClass] means private[OuterClass], but the JVM bytecode doesn’t have the same fine-grained access modifiers as Scala. It only has public, private, protected and default. And the semantics of those access modifiers do not always map 1-1 to the ones in Scala. So if private[OuterClass] in Scala has weaker access restrictions than private in the bytecode, the compiler has to translate it to public when writing the bytecode, or you would get all sorts of exceptions at runtime. This doesn’t influence the semantics of your Scala programs, but Java code would see those members as public.


#8

As a side note, private[this] also lets you have a mutable field of a covariant type, which simple private would not allow:

class C[+A] {
  private[this] var value: A = _
}

This class cannot be compiled with private instead of private[this].