我想有一个通用的矢量抽象类/特征来指定某些方法,例如:

trait Vec
{
  def +(v:Vec):Vec
  def *(d:Double):Vec

  def dot(v:Vec):Double
  def norm:Double
}


我想让Vec2DVec3D扩展Vec

class Vec2D extends Vec { /* implementation */ }
class Vec3D extends Vec { /* implementation */ }


但是,例如,如何使Vec2D只能添加到其他Vec2D而不能添加到Vec3D

现在,我只是在没有通用Vec2D祖先的情况下实现Vec3DVec,但这在重复代码中变得乏味。我必须实施依赖于这些类的所有几何类(例如TrianglePolygonMesh,...)两次,一次用于Vec2D,另一次用于Vec3D

我看到了Java实现:javax.vecmath.Vector2djavax.vecmath.Vector3d没有共同的祖先。这是什么原因呢?有没有办法在scala中克服它?

最佳答案

作为requested,设计基本特征的最有用的方法涉及到CRTPself-type annotation

trait Vec[T <: Vec[T]] { this: T =>
  def -(v: T): T
  def *(d: Double): T

  def dot(v: T): Double
  def norm: Double = math.sqrt(this dot this)
  def dist(v: T) = (this - v).norm
}


如果没有自类型,则无法调用this.dot(this),因为dot期望使用T;否则,将无法调用norm。因此我们需要通过注释来强制执行。

另一方面,没有CRTP,我们将无法在(this - v)上调用-,因为T返回T,因此我们需要确保类型T具有此方法,例如声明Vec[T]是。

08-25 01:00