Scala - how to create an anonymous class and not hide argument names

I often come across a situation where I have a factory method for some attribute, and the argument names conflict with the elements of the attribute, causing them to be hidden:

trait MyTrait { val a: Int val b: String } object MyTrait { def apply(a: Int, b: String): MyTrait = new MyTrait { val a = a // Recursive infinite loop. val b = b } } 

So usually I need to do something ugly, like:

  def apply(aA: Int, bB: String): MyTrait = new MyTrait { val a = aA val b = bB } 

or make local copies of the arguments:

  def apply(a: Int, b: String): MyTrait = { val localA = a val localB = b new MyTrait { val a = localA val b = localB } 

I would like the parameters of the apply method to be the same as the elements of my attribute, so that the client code reads well when I use named parameters: for example. MyTrait(a=3,b="123") .

Is there a mechanism that allows me to capture the outer region where the argument parameters are defined, but the anonymous class does not yet exist? For example, something like:

  def apply(a: Int, b: String): MyTrait = { outer => new MyTrait { val a = outer.a val b = outer.b } } 

Thanks!

+6
source share
2 answers

If we need to create an instance, why not delegate it to the constructor. So I can think of this hack:

 trait MyTrait { def a: Int def b: String } object MyTrait { private class MkMyTrait(val a: Int, val b: String) extends MyTrait def apply(a: Int, b: String): MyTrait = new MkMyTrait(a, b) } 
+2
source

My answer to a hoax that won't save much:

 trait T { val t: Int } object T { def apply(t: Int): T = new { private[this] val x = t } with T { val t = x } } 

In addition, -optimise does not get rid of the field.

Here's another idea: an alias for the parameter name.

Soon we will be able to selectively filter out warnings, so we can ignore the warning that is generated when the deprecation function is turned on:

 scala> :pa // Entering paste mode (ctrl-D to finish) trait T { val t: Int } object T { def apply(@deprecatedName('t) t0: Int): T = new T { val t = t0 } } // Exiting paste mode, now interpreting. defined trait T defined object T scala> T(t = 42) warning: there was one deprecation warning; re-run with -deprecation for details res1: T = T$$anon$1@6ea1bcdc 
+2
source

Source: https://habr.com/ru/post/974782/


All Articles