如何在Scala中的构造函数中设置实例成员?

Joz*_*cik 1 constructor scala member instance

在Scala中,我需要像Java中的代码一样:

public class A {
  private String text;  
  public A(String text) {
    this.text = text;
  }
}
Run Code Online (Sandbox Code Playgroud)

如何在Scala中实现这一目标?

我知道我可以使用class A(text: String) { ... },但这只是一个非常简单的例子而不是真实案例.

我尝试了以下内容,它始终打印为null:

class A {
  var text: String = null
  def this(text: String) = {
    this()
    this.text = text
  }
  println(text)
}
Run Code Online (Sandbox Code Playgroud)

感谢帮助.

ten*_*shi 6

在Scala类只有一个主构造函数,它正是你定义什么是这样的:class A(text: String) { ... }.所有其他构造函数应该首先调用它然后做自己的东西.

类的主体中的所有表达式都被视为主构造函数的主体.所以println(text)在你的情况下是在主构造函数的主体.你叫this()你的def this(text: String)构造函数的第一个,因此println被执行,只有这样,你初始化text场.


从我的角度来看,主构造函数可以满足大多数现实使用情况(特别是使用默认和命名参数).那么请您详细说明并解释为什么需要第二个?也许我们可以找到你面临的问题的解决方案.


关于评论的更新

如果要在构造期间提供一组可选参数,那么我建议您使用Option而不是null值.所以你可以A像这样实现你的类:

class A(val a: Option[String] = None, val b: Option[Int] = None, c: Option[Double] = Some(2.0)) 

new A(b = Some(10))
Run Code Online (Sandbox Code Playgroud)

所有字段现在都是常量并且有一些默认值,但您可以自定义其中一些字段.例如,根据某些业务逻辑,某些参数组合也可能是互斥的.在这种情况下,使用几个构造函数是合理的.但是更好的解决方案可以是在类的伴随对象中创建几个工厂方法,并使构造函数成为私有.例如,如果允许该类的用户提供a和/ bc,则可以编写如下内容:

class A private (val a: Option[String] = None, val b: Option[Int] = None, c: Option[Double] = Some(2.0)) 

object A {
    def apply(a: String, b: Int) = new A(Some(a), Some(b))
    def apply(c: Double) = new A(c = Some(c))
}

A("test", 1)
A(11.1)
Run Code Online (Sandbox Code Playgroud)