Como especifico um tipo vinculado a Float e Double em um tipo genérico no Scala?
-
27-09-2019 - |
Pergunta
Estou escrevendo algumas classes simples de vetores e matrizes.Eles se parecem com isto:
// 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)
}
Se eu continuar com outros métodos e classes como Point3f/d, Vector4f/d, Matrix3f/d, Matrix4f/d ...isso vai dar muito trabalho.Ufa...Então pensei que os genéricos poderiam ajudar aqui e remover a redundância da minha base de código.Pensei em algo assim:
// 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]
A ideia é que o compilador scala gere classes especializadas para Vector3[Float] e Vector3[Double] semelhantes a um modelo C++ faria.Infelizmente, tenho que colocar algum tipo vinculado ao parâmetro de tipo [T] da classe Vector3, de modo que o operador + seja definido em T.Minha pergunta:Como posso escrever Vector3[Float] que tenha as mesmas características de desempenho do Vector3f?Contexto:Gostaria de utilizar as classes Vector3f/Vector3d no código de detecção de colisão...então o desempenho é importante para mim.
Solução
Use um limite de contexto de Fracionário:
case class Vector3[@specialized(Float, Double) T : Fractional](x: T, y: T, z: T) { ...
então, dentro do corpo da classe, obtenha uma instância dos operadores aritméticos:
val fractOps = implicitly[Fractional[T]]
por último importe seus membros para o escopo da classe:
import fractOps._
Depois disso, você pode escrever operações infixas comuns em valores do tipo T usados na classe.Infelizmente, você terá que usar fractOps.div(a, b)
em vez de a / b
para divisão.