0

I am having a hard time understanding Private[this] when this Bind to a package vs Private[PackageName]

E.g.

This works fine:

package scopeA {

    private[scopeA] class PrivateClass1

    class PrivateClass2 extends PrivateClass1
}

But this does not

package scopeA {

    private[this] class PrivateClass1

    class PrivateClass2 extends PrivateClass1 //private class PrivateClass1 escapes its defining scope as part of type scopeA.PrivateClass1
}

However if i modify the second one as such:

package scopeA {

    private[this] class PrivateClass1

    private class PrivateClass2 extends PrivateClass1
}

private[this] or private, have the same effect in the last scenario.

I can see the difference, but i can't put proper words on it. Hence my question, what is the meaning of Private[this] when this bind to a package ? and is it different from private[PackageName], what's the exact difference between the two ?

There is something about escaping the scope that i am not sure to follow, why would it be ok with package name but not this ?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
MaatDeamon
  • 9,532
  • 9
  • 60
  • 127

1 Answers1

2

this refers to (possible) package object

package com {

  package object example {

    implicitly[this.type =:= com.example.`package`.type]

  }

}

According to the Scala Language Specification, packages are AnyRef values and have types. How does this make sense?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Great catch. Although it still does not fully answer the question ...or does it ? – MaatDeamon Nov 10 '20 at 05:12
  • @MaatDeamon I guess for ordinary object (not package object or package) behavior is the same. What does surprise you? – Dmytro Mitin Nov 10 '20 at 16:01
  • Well in my question i am not using package object at all. So unless there is an implicit package object ok. But still, what's the explicit rule here ? why `Private[this]` behave differently from `private[PackageName]` , I don't get it. It is no big deal if i don't get it, ultimately, but i was just curious about it. – MaatDeamon Nov 10 '20 at 17:22
  • I don't see many `private[this]` anyway, but i see more `private[PackageName]` – MaatDeamon Nov 10 '20 at 17:22
  • @MaatDeamon I propose to forget about package objects and packages for a moment. For ordinary object behavior is the same. https://scastie.scala-lang.org/cOUDS6PrR2eVu8bBJ68Qsg compiles, https://scastie.scala-lang.org/Ehgga90vTUiXnJq9BYK2lA doesn't compile, https://scastie.scala-lang.org/cGy6HXGPSSqQ0WMpWfURSA compiles. `private[scopeA]` means accessible in object `scopeA` and its companion class https://scastie.scala-lang.org/hszEiNQ7ROeuBbbAq3Qyuw while `private[this]` means accessible only inside the object https://scastie.scala-lang.org/TzWw9xYsQsS2PDKeJCvQvg – Dmytro Mitin Nov 10 '20 at 19:12
  • Ok i get it ! the question is, how do you translate that when package is involve ? – MaatDeamon Nov 10 '20 at 20:49
  • @MaatDeamon Rules can be the same for consistency. Package object can have companion class as well. – Dmytro Mitin Nov 10 '20 at 20:52
  • package is the class and package object is the implicit companion object ? . – MaatDeamon Nov 10 '20 at 20:52
  • make sense, final point now, how do you understand the "escapes its defining scope" ? I don't get it, why a public class can extend privateClass1 when [scopeA] and not when [this] ? – MaatDeamon Nov 10 '20 at 20:54
  • 1
    @MaatDeamon Let's consider an example with `val` rather than class: `object A { private class MyClass; val mc = new MyClass }`. Now `MyClass` escapes from scope because everyone outside can ask what the type of `A.mc` is. The answer is `A.MyClass` so `MyClass` leaks from `A`. I guess, for a class `PrivateClass2` its "type" is `typeSignature` i.e. `extends PrivateClass1`. – Dmytro Mitin Nov 10 '20 at 21:06
  • 1
    @MaatDeamon `typeOf[PrivateClass2].typeSymbol.typeSignature` is `PrivateClass1 ...` – Dmytro Mitin Nov 10 '20 at 21:12
  • @MaatDeamon *"package is the class and package object is the implicit companion object ?"* Well, I guess package, package object and its companion class are three different entities (with types `example.type`, ``example.`package`.type`` and `example`). But it seems companion class of package object is not always allowed. `package object example; class example` compiles while `package com { package object example; class example }` doesn't (Scala 2.13.3). – Dmytro Mitin Nov 10 '20 at 23:02