如何在Scala中的泛型类型上为Float和Double绑定类型?

gru*_*ewa 1 generics scala type-bounds

我正在编写一些简单的Vector和Matrix类。他们看起来像这样:

// 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)
}
Run Code Online (Sandbox Code Playgroud)

如果我继续使用Point3f / d,Vector4f / d,Matrix3f / d,Matrix4f / d等其他方法和类,这将需要大量工作。Uff ...所以我认为泛型可以在这里提供帮助,并从我的代码库中删除冗余。我想到了这样的事情:

// 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]
Run Code Online (Sandbox Code Playgroud)

这个想法是,scala编译器为Vector3 [Float]和Vector3 [Double]生成专门的类,类似于C ++模板。不幸的是,我必须在Vector3类的类型参数[T]上加上一些类型绑定,以便在T上定义运算符+。我的问题:如何编写具有与Vector3f相同性能特征的Vector3 [Float]?上下文:我想在碰撞检测代码中使用Vector3f / Vector3d类……因此性能对我来说确实很重要。

Ran*_*ulz 5

使用分数的上下文绑定:

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

然后在类的主体内,获取算术运算符的实例:

  val fractOps = implicitly[Fractional[T]]
Run Code Online (Sandbox Code Playgroud)

最后将其成员导入该类的范围:

  import fractOps._
Run Code Online (Sandbox Code Playgroud)

之后,您可以对类中使用的T类型的值编写普通的中缀操作。可悲的是,您将不得不使用fractOps.div(a, b)而不是a / b进行除法。