3

私は 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" に渡すことができるのはなぜですか? または文字 "_" に別の文字があるこの文脈での意味は?

4

1 に答える 1

1

@ghik が言うように、メソッド (またはこの場合はコンストラクター) のオーバーロードを使用する場合、型推論の制限があります。一般に、過負荷を避けるように努めるべきですが、それはほとんど良い習慣ではありません。

ここでの回避策は、2 番目のパラメーター リストを使用することです。

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)

関数の引数を 2 番目のパラメーター リストに入れることは、関数リテラルの便利な構文を使用できるため、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 }

(注: 1 つのapplyパラメーター リストを使用してメソッドを記述することもできます。オーバーロードされていないため、アンダースコアを記述しなければならないという問題はありません)

于 2013-08-26T21:43:05.760 に答える