Comment puis-je spécifier un type lié à flotteur et double sur un type générique Scala?

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

  •  27-09-2019
  •  | 
  •  

Question

Je suis en train d'écrire quelques simples cours vectorielles et matricielles. Ils ressemblent à ceci:

// 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)
}

Si je vais avec des méthodes et des autres classes comme Point3f / d, Vector4f / j, Matrix3f / j, Matrix4f / d ... cela va être beaucoup de travail. Uff ... Donc, je pensais que les médicaments génériques pourrait possible l'aide ici et supprimer la redondance de ma base de code. Je pensais à quelque chose comme ceci:

// 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]

L'idée est que le compilateur scala génère des classes spécialisées pour Vector3 [Float] et Vector3 [Double] similaire en C ++ modèle ferait. Malheureusement, je dois mettre un certain type lié au paramètre de type [T] de classe Vector3 telle que l'opérateur + est défini sur T. Ma question: Comment puis-je écrire Vector3 [Float] qu'il a les mêmes caractéristiques de performance que Vector3f? Contexte:. Je voudrais utiliser les classes Vector3f / Vector3D dans le code de détection de collision ... si la performance est importante pour moi

Était-ce utile?

La solution

Utiliser un contexte lié de Fractional:

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

puis dans le corps de la classe, obtenir une instance des opérateurs arithmétiques:

  val fractOps = implicitly[Fractional[T]]

enfin importer ses membres dans le cadre de la classe:

  import fractOps._

Vous pouvez ensuite écrire des opérations infixes ordinaires sur les valeurs de type T utilisé dans la classe. Malheureusement, vous devrez utiliser fractOps.div(a, b) au lieu de a / b pour la division.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top