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!
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