Scala类成员和构造函数参数名称冲突

Bru*_*eis 20 constructor scala field properties

考虑以下用Java编写的类:

class NonNegativeDouble {
    private final double value;
    public NonNegativeDouble(double value) {
        this.value = Math.abs(value);
    }
    public double getValue() { return value; }
}
Run Code Online (Sandbox Code Playgroud)

它定义了一个名为final的字段value,该字段在构造函数中初始化,方法是将其参数称为alike并对其应用函数.

我想在Scala中写一些类似的东西.起初,我尝试过:

class NonNegativeDouble(value: Double) {
  def value = Math.abs(value)
}
Run Code Online (Sandbox Code Playgroud)

但编译器抱怨:错误:重载方法值需要结果类型

显然编译器认为表达式中value的表达式Math.abs(value)是指被定义的方法.因此,定义的方法是递归的,所以我需要声明它的返回类型.所以,我写的代码没有按照我的预期去做:我想value在里面Math.abs(value)引用构造函数参数value,而不是指定义的方法.这是因为如果编译器隐式添加一个this.Math.abs(this.value).

添加valvar(或private ...变体)构造函数参数似乎没有帮助.

所以,我的问题是:我可以定义一个与构造函数参数同名的属性,但可能是一个不同的值?如果是这样,怎么样?如果没有,为什么?

谢谢!

Dan*_*ral 17

不,你不能.在Scala中,构造函数参数属性,因此重新定义它们是没有意义的.

当然,解决方案是使用另一个名称:

class NonNegativeDouble(initValue: Double) {
  val value = Math.abs(initValue)
}
Run Code Online (Sandbox Code Playgroud)

像这样使用,initValue不会是创建的实例的一部分.但是,如果您在def模式匹配声明中使用它,那么它将成为该类的每个实例的一部分.

  • 构造函数不是属性,除非它是一个case类或用val或var注释.它可以在类定义中的任何位置使用. (9认同)
  • @Bruno - 有几个命名约定; 我个人喜欢名字附加0的那个,因为零意味着一个起点,而且很简短.(下划线有时会被添加或附加,但我个人觉得已经有很多下划线了.) (2认同)
  • @Geoff这是私人财产。 (2认同)