4

C++/テンプレートの世界から scala に移行するのに苦労しています。T をインスタンス化するために使用するものがそれらの操作をサポートしている限り、必要なテンプレート パラメーター T に対して任意の操作を使用できることに慣れています (基本的にコンパイル時のダック タイピング)。単一の型パラメーターを持つ抽象クラスを定義できるようにし、型 T の特定のインターフェイスを期待する対応するイディオムを Scala で見つけることができません。

私が持っているものはほとんど機能しますが、T が Int からの変換/構築をサポートしていることを抽象クラス (Texture[T <: Summable[T]]) に伝える方法がわかりません。T が変換をサポートしていることを Texture が認識できるように、トレイト Summable に暗黙的な変換を追加するにはどうすればよいですか?

trait Summable[T] { 
   def += (v : T) : Unit
   def -= (v : T) : Unit   
}

object Int4 { implicit def int2Int4(i : Int) = new Int4(i, i, i, i) }

class Int4 (var x : Int, var y : Int, var z : Int, var w : Int) extends Summable[Int4] {
   def this (v : Int) = this(v, v, v, v)
   def += (v : Int4) : Unit = { x += v.x; y += v.y; z += v.z; w += v.w }
   def -= (v : Int4) : Unit = { x -= v.x; y -= v.y; z -= v.z; w -= v.w } 
}

abstract class Texture[Texel <: Summable[Texel]] {
   var counter : Texel
   def accumulate(v : Texel) : Unit = { counter += v }
   def decrement() : Unit = { counter -= 1 } //< COMPILE ERROR HERE, fails to find implicit
}

class Int4Target extends Texture[Int4] {
   var counter : Int4 = new Int4(0, 1, 2, 3)
}
4

3 に答える 3

4

このような暗黙のコンストラクターパラメーターを定義できます

abstract class Texture[Texel <: Summable[Texel]](implicit int2Texel: Int => Texel) {
//...

これは基本的に、のインスタンスを構築するために、からにTexture使用可能な暗黙の変換関数が必要であることをコンパイラに通知します。スコープ内のどこかにそのような関数が定義されていると仮定すると(これは実行します)、コンパイルエラーは発生しなくなります。IntTexel

Edit2:わかりました、私はもともとあなたのコードを読み間違えました、あなたは実際にからの1つの暗黙のパラメータだけを必要としますInt => Texel。あなたのコードは上記の変更で私のためにコンパイルされます。

編集:変数を適切に再割り当てするにはTexel => Int、実際には2つの変換関数が必要です。Int => Texel

于 2012-02-12T02:41:42.677 に答える
3

C++ テンプレートと Scala の他のものとの基本的な違いは、C++ テンプレートは使用ごとにコンパイルされることです。つまり、 と でテンプレートを使用するintdouble、2 つの異なるクラスがコンパイルされ、一部のコードが実際に作成されたときにのみコンパイルされます。それの使用。

一方、Scala には個別のコンパイルがあります。JVM の制限を考えると、Java ほど良くはありませんが、それでも基本原則に従っています。したがって、何かに型パラメーターがある場合でも、宣言時にコンパイルされ、そのようなクラスは 1 つしか存在しません。そのコンパイルされたコードは、呼び出すことができるすべての可能なパラメーターをサポートする必要があるため、テンプレートとはかなり異なる制限が生じます。

トレイトと暗黙の変換に関しては、トレイトはパラメーターをサポートしておらず、暗黙の変換 (ビュー境界) はパラメーターです。代わりに、クラスを使用してください。

于 2012-02-12T07:12:48.723 に答える
2

Scalaでは、トレイトの型パラメーターに対して暗黙の変換が存在することを要求することはできません。これには正当な理由があります。次のような特性を定義したとします。

trait ATrait[T <% Int] {
    def method(v: T) { println(v: Int) }
}

そして、2つの場所でそれのインスタンスを作成しました:

package place1 {
    implicit def strToInt(s: String) = 5
    val inst = new ATrait[String]
}

package place2 {
    implicit def strToInt(s: String) = 6
    val inst = new ATrait[String]
}

そして、これらのインスタンスを次のように使用しました。

val a = if (someTest) place1 else place2
a.method("Hello")

これを印刷する必要があります56?つまり、どの暗黙の変換を使用する必要がありますか?暗黙はコンパイル時に検出する必要がありますが、オブジェクトの作成にどの暗黙の変換が存在したかはわかりません。

言い換えると、暗黙は、それらが使用されるオブジェクトではなく、それらが使用されるスコープによって提供されます。後者は不可能です。

だから、あなたの問題について。暗黙的なメンバーを使用する代わりに、通常のメンバーを使用できます。

trait Summable[T] { 
   def -= (v: T): Unit
   def -= (v: Int) { this -= (encode(v)) }

   def encode(i: Int): T
}

class Int4 (var x: Int, var y: Int, var z: Int, var w: Int) extends Summable[Int4] {
   def -= (v : Int4) : Unit = { x -= v.x; y -= v.y; z -= v.z; w -= v.w } 

   def encode(i: Int) = Int4.int2Int4(i)
}

これで、decrementメソッドは正しくコンパイルされます。

別の言い方をすれば、暗黙を型に属するプロパティとは考えないでください(つまり、「Intから暗黙的に変換できる」はInt4のプロパティではありません)。これらは値であり、タイプを使用して識別できます。

お役に立てれば。

于 2012-02-12T02:25:34.100 に答える