我一直在学习Scala,到目前为止一直很好,遗憾的是我发现了一些我不完全理解的行为。我希望你们能给我一些线索,当我编写这门课时出现问题:
class Point(iDim:Int,data:Array[Double],f: Array[Double] => Double) {
...
def this(idim: Int, obj :ObjectThatGenerate_ArrayofDouble, f: Array[Double] => Double){
this(idim,obj.generateArray(idim),f)
}
}
所以当我在主代码中使用这些构造函数时,我需要这样做
var p:Point = new Point (idim,obj,f _)
或
var p:Point = new Point (idim,dataArray,f _)
但是如果我删除了辅助构造函数,我只需要像这样构建对象:
var p:Point = new Point (idim, dataArray, f)
为什么在Scala中我有一个辅助构造函数我需要传递一个部分实现的函数“f _”而当我没有辅助构造函数时我可以直接传递函数“f”?或者字符“_ “在这种情况下还有其他意义吗?
答案 0 :(得分:1)
正如@ghik所说,当你使用方法(或者在这种情况下是构造函数)重载时,存在类型推断限制。一般来说,你应该尽量避免超载,这几乎不是好习惯。
这里的解决方法是使用第二个参数列表,例如
trait Generator {
def generateArray(idim: Int): Array[Double]
}
class Point(iDim: Int, data: Array[Double], f: Array[Double] => Double) {
def this(idim: Int, gen: Generator)(f: Array[Double] => Double) {
this(idim, gen.generateArray(idim), f)
}
}
val obj = new Generator {
def generateArray(idim: Int) = new Array[Double](idim)
}
def f(arr: Array[Double]) = arr.sum
new Point(33, obj)(f)
将函数参数放入第二个参数列表在Scala中很常见,因为它为函数文字提供了方便的语法。因为new Point(...) { ... }
将被解释为使用匿名主体扩展类,更好的解决方案 - 并摆脱重载 - 是使用配套对象:
object Point {
def apply(idim: Int, gen: Generator)(f: Array[Double] => Double) =
new Point(idim, gen.generateArray(idim), f)
}
class Point(iDim: Int, data: Array[Double], f: Array[Double] => Double)
Point(33, obj)(f)
Point(33, obj) { arr => arr.sum / arr.size }
(注意:您也可以使用一个参数列表编写apply
方法。因为它没有重载,所以您不必告知必须说明下划线)< / p>