Scala辅助构造函数行为

Scala辅助构造函数行为,scala,Scala,在Cay Horstmann的《不耐烦的人的Scala》一书中,关于第5章练习8,有一个问题: //Make a class Car with read-only properties for manufacturer, model name, //and model year, and a read-write property for the license plate. Supply four // constructors. All require the manufacturer a

在Cay Horstmann的《不耐烦的人的Scala》一书中,关于第5章练习8,有一个问题:

//Make a class Car with read-only properties for manufacturer, model name,
//and model year, and a read-write property for the license plate. Supply four
//  constructors. All require the manufacturer and model name. Optionally,
//model year and license plate can also be specified in the constructor. If not,
//the model year is set to -1 and the license plate to the empty string. Which
//constructor are you choosing as the primary constructor? Why?
所以我给班级编了代码:

case class Car(val manufacturer: String, val modelName: String,
                 val modelYear: Int, var licensePlate : String = "") {
    def this(manufacturer: String, modelName: String, licensePlate: String) {
      this(manufacturer, modelName, -1, licensePlate)
    }

    def this(manufacturer: String, modelName: String, modelYear: Int) {
具体而言,关于这一部分:

      this(manufacturer, modelName, modelYear)
    }

    def this(manufacturer: String, modelName: String) {
      this(manufacturer, modelName, -1)
    }
  }
编译器报告错误:

<console>:14: error: called constructor's definition must precede calling constructor's definition
             this(manufacturer, modelName, modelYear)
             ^
或者,如果我使类主构造函数没有licensePlate的默认值(当然,调整过程中的其他辅助构造函数调用)

请注意,该问题专门针对4个构造函数提出,因此实例创建可以被称为:

new Car("Honda", "City", 2010, "ABC-123")
new Car("Honda", "City")
new Car("Honda", "City", "ABC-123")
new Car("Honda", "City", 2010)
提前感谢那些能够阐明这个问题的人

====

感谢Ende Neu和Kigyo的回答,这看起来是一个完美的解决方案(删除递归构造函数):

案例级汽车(val制造商:字符串,val型号名称:字符串,
val modelYear:Int=-1,var licensePlate:String=“”){
定义此(制造商:字符串,型号名称:字符串,许可证编号:字符串){
此(制造商,型号,-1,许可证)
}
>
}
控制台println新车(“本田”,“城市”,2010年,“ABC-123”)
控制台println新车(“本田”、“城市”)
控制台println新车(“本田”、“城市”、“ABC-123”)
控制台println新车(“本田”,“城市”,2010年)

之所以出现此错误,是因为scala编译器无法看到您在case类中提供的默认值,并且您正在使用三个参数而不是四个参数声明构造函数,例如:

case class Test(a: String, b: String, c: String = "test") {
  def this(d: String, e: String) = this(c, e)
}
这将引发相同的错误,您可以做的是在构造函数中指定默认值,就像处理空字符串一样:

def this(d: String) = this(d, "empty")
def this(d: String, e: String) = this(d, e, "empty") // and this would return a new object
具有默认值的case类只对应于一个构造函数,在该构造函数中,您不必提供所有参数,因此在练习中,您不需要两个构造函数,如果未指定年份和板块,请使用一些预先定义的值,否则使用默认构造函数(已包含4个参数):

然后这样称呼它:

new Car("Wolksvagen", "Polo")
Car("Ford", "Fiesta", 1984, "plate")

请注意,您必须在第一个声明中使用
new
关键字,因为它不是指伴随对象中的apply方法(也可以被覆盖,请参见此)。

我只想澄清一些事情

在本例中,可以省略最后一个参数。这里我们调用主构造函数,它有3个参数,只提供两个。(与Ende Neu的例子相关)

那么,为什么它在您的场景中不起作用呢?仔细看看

def this(manufacturer: String, modelName: String, modelYear: Int) {
  this(manufacturer, modelName, modelYear)
}
这里您也省略了最后一个参数,但是您定义的新构造函数正好接受了那个数量的参数,这使得它成为一个递归调用。因此,您从不调用主构造函数,因此会出现错误


我还将删除您案例中的默认值。也许有办法解决,但我现在太累了。

你的
测试中有一个打字错误。应该是
def this(d:String,e:String)=this(d,e)
很高兴知道,这本书中强调得不够。但是,这个问题专门针对4个构造函数提出,因此我想我会使用这个解决方案来删除主构造函数中的默认值,这样我可以像这样调用实例创建(所有4个变量):新车(“本田”,“城市”,2010,“ABC-123”)新车(“本田”,“城市”)新车(“本田”,“城市”,“ABC-123”)新车(“本田”,“城市”,2010)我不打算在这里进行递归调用,但看起来确实如此。我被这样一个事实蒙蔽了双眼:通过这样做,我调用了接受4个参数的主构造函数。我想你是对的,scala编译器应该会以编译错误作出反应。我想完美的解决方案是删除此构造函数。我错过了,可能对我来说太晚了,事实上这是正确的答案。如果您现在在这条路上,还可以为
modelYear
设置默认值。然后还可以删除最后一个构造函数。我以为你的想法是要有四名施工人员我们是完美主义者吗,Kigyo?我再次更新了它(见上文)。现在这并不是那么完美。尽管我在主构造函数中有一个默认值,但我仍然在辅助构造函数中将a-1传递给模型年。这能进一步改进吗?我在这种情况下没有发现任何改进:(
case class Car(val manufacturer: String, val modelName: String, val modelYear: Int, var licensePlate : String) {
  def this(manufacturer: String, modelName: String) =
    this(manufacturer, modelName, -1, "")
  }
}
new Car("Wolksvagen", "Polo")
Car("Ford", "Fiesta", 1984, "plate")
case class Test(a: String, b: String, c: String = "test") {
  def this() = this("", "")
}
def this(manufacturer: String, modelName: String, modelYear: Int) {
  this(manufacturer, modelName, modelYear)
}