在Scala中,如何在类的主构造函数中定义局部参数? [英] In Scala, how do you define a local parameter in the primary constructor of a class?

查看:403
本文介绍了在Scala中,如何在类的主构造函数中定义局部参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scala中,如何在不是数据成员的类的主构造函数中定义一个局部参数,并且例如仅用于初始化基类中的数据成员?



例如,在下面的代码中,我如何正确定义 B类的主构造函数中的参数 b

 类A(var a:Int)
B类(?b?)扩展A(b)






Randall,你的答案解释了为什么当我引入一个方法 inc 增加属性 a ,而且更改类 B 构造函数中的参数名称以匹配类 A中的参数的名称构造函数:

  class A(var a:Int)
class B Int)extends A(a){
def inc(value:Int){this.a + = value}
}

Scala编译器输出:

  $ scala construct.scala 
。 scala:3:错误:重新分配到val
def inc(value:Int){this.a + = value}
^
发现一个错误

Scala抱怨,因为 B 现在必须有一个私有的只读属性<$ c由于在 inc 中引用 a ,$ c> a 。将 B(a:Int)更改为 B(var a:Int)会生成不同的编译器错误:

  construct.scala:2:error:错误覆盖Int类型A中的变量a; 
变量a需要`override'修饰符
类B(var a:Int)extends A(a){
^
发现一个错误

添加覆盖无助于:

  construct.scala:2:error:错误覆盖Int类型A中的变量a; 
变量a不能覆盖可变变量
类B(覆盖变量a:Int)extends A(a){
^
发现一个错误

如何在 B 的主构造函数中的参数中使用相同的名称作为基类的主构造函数中定义的属性 A

$

解决方案

如果从构造函数参数中删除var或val关键字,则不会生成属性。



请注意, ,非val构造函数参数在范围内并且在整个类中可访问。如果在非构造函数代码中使用一个(即在一个方法的主体中),在生成的类中将存在一个不可见的私有字段,该私有字段保存该构造函数参数,就好像你将它设置为private var或 private val构造函数参数。



附录(比迟到更好):



在此代码中,对构造函数的引用仅出现在构造函数体中:

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

...这里的值 i 仅在执行构造函数时存在。

但是,在下面的代码中,因为构造函数参数是在方法体中引用的,而不是构造函数体的一部分 - 构造函数参数必须复制到(私有)字段生成的类(增加其内存需求的4个字节需要持有 Int ):

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

def mod(d:Int)= i%d
}


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 member in the base class?

For example, in the following code, how could I properly define parameter b in the primary constructor of class B so that it generates only a temporary local parameter and not a data member?

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


Randall, your answers explain why the Scala compiler complains when I introduce a method inc that increments the property a, but also change the name of the parameter in the class B constructor to match that of the parameter in the class A constructor:

class A(var a: Int)
class B(a: Int) extends A(a) {
  def inc(value: Int) { this.a += value }
}

Scala compiler output:

$ scala construct.scala
construct.scala:3: error: reassignment to val
  def inc(value: Int) { this.a += value }
                               ^
one error found

Scala complains because class B must now have a private, read-only property a due to the reference to a in inc. Changing B(a: Int) to B(var a: Int) generates a different compiler error:

construct.scala:2: error: error overriding variable a in class A of type Int;
 variable a needs `override' modifier
class B(var a: Int) extends A(a) {
            ^
one error found

Adding override doesn't help, either:

construct.scala:2: error: error overriding variable a in class A of type Int;
 variable a cannot override a mutable variable
class B(override var a: Int) extends A(a) {
                 ^
one error found

How can I use the same name in the parameter in the primary constructor of B as the property defined in the primary constructor of the base class A?

解决方案

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
}

这篇关于在Scala中,如何在类的主构造函数中定义局部参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆