2011-09-06 5 views
11

は、私がScalaでは、単純な2Dのポイントクラスを定義だと言うと、私は、様々なタイプでそれを構築することができるようにしたい:Scalaの補助コンストラクタで型パラメータを使用できないのはなぜですか?

私のような、テンプレートを使用して、これを煮詰めるたい
class Point(x:Float, y:Float) { 
    this(x:Double, y:Double) = this(x.toFloat, y.toFloat) 
    this(x:Int, y:Int) = this(x.toFloat, y.toFloat) 
    // etc... 
} 

class Point(x:Float, y:Float) { 
    this[T](x:T, y:T) = this(x.toFloat, y.toFloat) 
} 

私はTがtoFloatが定義されていないタイプである可能性があるので、これはとにかく動作しません知っているが、私が手にコンパイルエラーがある:

no type parameters allowed here

はこのちょうどUNSUPPですScalaでorted?もしそうなら、なぜ、これを回避する簡単な方法がありますか?

答えて

14

スカラのクラスコンストラクタ(Javaとは異なります)は型パラメータを取ることができません。クラス自体だけができます。 Scalaがこのデザインを選択した理由については、主な理由はシンプルさだと思います。

一般的なセカンダリ "ビルダー"メソッドを使用する場合は、コンパニオンオブジェクトでそれを定義するのが自然です。例えば、

object Point { 
    def build[T : Numeric](x: T, y: T) = { 
    val n = implicitly[Numeric[T]] 
    new Point(n.toFloat(x), n.toFloat(y)) 
    } 
} 

class Point(val x:Float, val y:Float) 

val p = Point.build(1, 2) // Companion object's builder 
p.x + p.y 

は、ここで私は、ジェネリックtoFloatメソッドを取得するためにNumeric型クラスを使用しました。

+1

このメソッドを 'apply'と呼ぶと' val p = Point(1,2) 'と書くことができます。 –

+1

はい、それはケースクラスがそれを行う方法です。 –

3

は私が...として「近い」となって、しばらくの間、このと遊ん

になり
class Point(x:Float, y:Float) { 
    def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat) 
} 

...「エラー:ここでは許可されていない型パラメータ」(ちょうどポストあたりとして)とその後、私は実現しました...

初期化子が型パラメータを取ることができるならば、もしあれば、クラスパラメータで曖昧になります。これはが言語仕様ではうまくいきませんでしたが、それはもっと複雑なケースです。 Javaの相互運用性の問題もあります。

class Foo[T](x: T) { 
    def this[X](z: X) = ... 
} 
new Foo[Int](42) // T is Int? X is ...? Or ...? 

は個人的に私は、Scalaはエッフェル状パターン(のみという名前のコンストラクタまたは「ファクトリメソッド」)を続いたいが、残念ながら、それはScalaのではないでしょう。

を想像してみてください。

ハッピーコーディング。

関連する問題