Wie gebe ich einen Typen für Float und Double auf einem generischen Typ in Scala gebunden?

StackOverflow https://stackoverflow.com/questions/3462983

  •  27-09-2019
  •  | 
  •  

Frage

Ich schreibe ein paar einfache Vektor und Matrix-Klassen. Sie sehen aus wie folgt aus:

// Vector with Floats
case class Vector3f(x: Float, y: Float, z: Float) {
  def +(v: Vector3f) = Vector3f(x + v.x, y + v.y, z + v.z)
}

// Vector with Doubles
case class Vector3d(x: Double, y: Double, z: Double) {
  def +(v: Vector3d) = Vector3d(x + v.x, y + v.y, z + v.z)
}

Wenn ich mit weiteren Methoden weitergehen und Klassen wie Point3f / d, Vector4f / d, Matrix3f / d, Matrix4f / d ... das wird eine Menge Arbeit sein. Uff ... Also dachte ich Generika konnte mögliche Hilfe hier und entfernen Redundanz von meiner Code-Basis. Ich dachte an so etwas wie folgt aus:

// first I define a generic Vector class
case class Vector3[@specialized(Float, Double) T](x: T, y: T, z: T) {
   def +(v: Vector3[T]) = new Vector3[T](x + v.x, y + v.y, z + v.z)
}

// than I use some type aliases to hide the generic nature
type Vector3f = Vector3[Float]
type Vector3d = Vector3[Double]

Die Idee ist, dass die scala Compiler Klassen für Vector3 [Float] und Vector3 [Double] ähnlich wie ein C ++ Vorlage tun würde, spezialisiert erzeugt. Leider muss ich auf dem Typparameter [T] der Klasse Vector3, so dass der Betreiber verpflichtet, irgendeine Art setzen + auf T. Meine Frage definiert ist: Wie kann ich Vector3 [Float] schreiben, dass es die gleichen Leistungsmerkmale wie Vector3f hat? Kontext:. Ich mag die Vector3f / Vector3D Klassen in Kollisionserkennungscode verwenden ... so die Leistung für mich nicht egal

War es hilfreich?

Lösung

Verwenden Sie einen Kontext gebunden von Fractional:

case class Vector3[@specialized(Float, Double) T : Fractional](x: T, y: T, z: T)  { ...

dann innerhalb des Körpers der Klasse eine Instanz der arithmetischen Operatoren erhalten:

  val fractOps = implicitly[Fractional[T]]

schließlich seine Mitglieder in den Gültigkeitsbereich der Klasse importieren:

  import fractOps._

Danach können Sie gewöhnliche Infix Operationen auf Werten vom Typ T schreiben innerhalb der Klasse verwendet. Leider müssen Sie fractOps.div(a, b) statt a / b für die Division verwendet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top