In Scala, how do you define a local parameter in the primary constructor of a class?

后端 未结 4 2050
走了就别回头了
走了就别回头了 2020-12-16 22:32

In Scala, how does one define a local parameter in the primary constructor of a class that is not a data member and that, for example, serves only to initialize a data membe

相关标签:
4条回答
  • 2020-12-16 22:37

    You can create temporary variables throughout the initialization of single class members like this:

    class A(b:Int){
      val m = {
        val tmp = b*b
        tmp+tmp
      }
    }
    
    0 讨论(0)
  • 2020-12-16 22:44

    After some experimentation, I determined that simply leaving out var or val in front of the parameter b will make it a local parameter and not a data member:

    class A(var a: Int)
    class B(b: Int) extends A(b)
    

    Java expansion:

    $ javap -private B
    Compiled from "construct.scala"
    public class B extends A implements scala.ScalaObject{
        public B(int);
    }
    
    $ javap -private A
    Compiled from "construct.scala"
    public class A extends java.lang.Object implements scala.ScalaObject{
        private int a;
        public A(int);
        public void a_$eq(int);
        public int a();
        public int $tag()       throws java.rmi.RemoteException;
    }
    

    Notice that class A has a private data member a due to the var a: Int in its primary constructor. Class B, however, has no data members, but its primary constructor still has a single integer parameter.

    0 讨论(0)
  • 2020-12-16 22:46

    Derek,

    If you have this:

    class A(a: Int) {
      val aa = a // reference to constructor argument in constructor code (no problem)
      def m: Float = a.toFloat // reference to constructor argument in method body (causes a to be held in a field)
    }
    

    you'll find (using javap, e.g.) that a field named "a" is present in the class. If you comment out the "def m" you'll then see that the field is not created.

    0 讨论(0)
  • 2020-12-16 22:48

    If you remove the "var" or "val" keyword from the constructor parameter, it does not produce a property.

    Be aware, though, that non-var, non-val constructor parameters are in-scope and accessible throughout the class. If you use one in non-constructor code (i.e., in the body of a method), there will be an invisible private field in the generated class that holds that constructor parameter, just as if you made it a "private var" or "private val" constructor parameter.

    Addendum (better late than never??):

    In this code the references to the constructor parameter occur only in the constructor body:

    class C1(i: Int) {
      val iSquared = i * i
      val iCubed = iSquared * i
      val iEven = i - i % 2
    }
    

    ... Here the value i exists only during the execution of the constructor.

    However, in the following code, because the constructor parameter is referenced in a method body—which is not part of the constructor body—the constructor parameter must be copied to a (private) field of the generated class (increasing its memory requirement by the 4 bytes required to hold an Int):

    class C2(i: Int) {
      val iSquared = i * i
      val iCubed = iSquared * i
      val iEven = i - i % 2
    
      def mod(d: Int) = i % d
    }
    
    0 讨论(0)
提交回复
热议问题