2013-08-26 1 views
2

Я изучаю Scala, это было так хорошо до сих пор, к сожалению, я обнаружил определенное поведение, которое я не совсем понимаю. Я надеюсь, что вы, ребята, можете дать мне некоторые подсказки, проблема возникла, когда я закодирован этот класс:понимание поведения 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»? Или символ « _ "имеют в этом контексте другое значение?

+1

Это выглядит как неудачное ограничение вывода типа, которое здесь имеет некоторые проблемы с перегруженными конструкторами. – ghik

ответ

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 с один список. Поскольку он не перегружен, у вас нет проблемы с тем, чтобы указать подчеркивание)

Смежные вопросы