¿Cómo se especifica un tipo con destino a flotado y doble en un tipo genérico en Scala?

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

  •  27-09-2019
  •  | 
  •  

Pregunta

Estoy escribiendo algunas simples clases de vectores y matrices. Son similares a esto:

// 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 voy con otros métodos y clases como Point3f / d, Vector4f / d, Matrix3f / d, Matrix4f / d ... esto va a ser un montón de trabajo. Uff ... Así que pensé genéricos podría posible ayuda aquí y redundancia Sacar de mi base de código. Pensé en algo como esto:

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

La idea es que el compilador genera Scala clases especializadas para Vector3 [Flotante] y Vector3 [doble] similar a una plantilla de C ++ haría. Por desgracia tengo que poner algún tipo con destino en el parámetro de tipo [T] de la clase Vector3 de tal manera que el operador + se define en T. Mi pregunta: ¿Cómo puedo escribir Vector3 [Flotante] que tiene las mismas características de rendimiento como Vector3f? Contexto:. Me gustaría utilizar las clases Vector3f / Vector3D en código de detección de colisiones ... lo que el rendimiento importa para mí

¿Fue útil?

Solución

El uso de un contexto ligado fraccional:

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

entonces dentro del cuerpo de la clase, obtener una instancia de los operadores aritméticos:

  val fractOps = implicitly[Fractional[T]]

Por último importar sus miembros en el ámbito de la clase:

  import fractOps._

A partir de entonces se puede escribir operaciones infijas ordinarias en valores de tipo T se utiliza dentro de la clase. Por desgracia, tendrá que utilizar fractOps.div(a, b) en lugar de a / b para la división.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top