scalaaccess-modifiersanonymous-inner-class

Getting error when instantiating a trait within a class (method became private)


In the following code, I'm trying to instantiate the trait A with the Decorator class and add a method p to it so I can get another object A but with a p method:

trait A {
  def x: Int
}

case class Decorator(a: A) {
  def withPrint: A = new A {
    val x = 100
    def p: Unit = println(x)
  }
}

val a = new A {val x = 100}

val d = Decorator(a).withPrint

But when I try to call d.p it gives error

value p is not a member of A$A54.this.A

Also then I print the declared methods in d I see p is private!

d.getClass.getDeclaredMethods.foreach(println)

# public int stringsimilarity.A$A55$A$A55$Decorator$$anon$2.x()
# private void stringsimilarity.A$A55$A$A55$Decorator$$anon$2.p()

Could anyone explain why this happens? Any help will be really appreciated!! Thank you!


Solution

  • There is no reason why def p should be public. It's a method that you defined in a local anonymous class that implements trait A. The trait A declares only public method x, and nothing else. Therefore, the only scope where you have access to p is inside of the initializer of the new A { ... }, so private seems appropriate for that.

    If you want to expose the method p, you can either add it to A (then you have to implement it there, and then you also don't need the withPrint method at all), or mix in an additional trait that guarantees the presence of method p. For example:

    trait A {
      def x: Int
    }
    
    trait Print {
      def p: Unit
    }
    
    case class Decorator(a: A) {
      def withPrint: A with Print = new A with Print {
        val x = 100
        def p: Unit = println(x)
      }
    }
    
    val a = new A { val x = 100 }
    
    val d = Decorator(a).withPrint
    
    d.p