Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
928 views
in Technique[技术] by (71.8m points)

oop - proper class hierarchy for 2D and 3D vectors

I want to have a general vector abstract class / trait that specifies certain methods, e.g.:

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

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

I want to have Vec2D and Vec3D extend Vec:

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

But how can I, for instance, make it so that Vec2D can only be added to other Vec2D and not to Vec3D?

Right now I'm just implementing Vec2D and Vec3D without a common Vec ancestor, but this is getting tedious with duplicate code. I have to implement all my geometry classes that depend on these classes (e.g. Triangle, Polygon, Mesh, ...) twice, once for Vec2D and again for Vec3D.

I see the java implementations: javax.vecmath.Vector2d and javax.vecmath.Vector3d do not have a common ancestor. What's the reason for this? Is there a way to overcome it in scala?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use self types:

trait Vec[T] { self:T =>
  def +(v:T):T
  def *(d:Double):T

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

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

But if both implementations are very similar, you could also try to abstract over the Dimension.

sealed trait Dimension
case object Dim2D extends Dimension
case object Dim3D extends Dimension

sealed abstract class Vec[D <: Dimension](val data: Array[Double]) { 

  def +(v:Vec[D]):Vec[D] = ...
  def *(d:Double):Vec[D] = ...

  def dot(v:Vec[D]):Double = ...
  def norm:Double = math.sqrt(data.map(x => x*x).sum)
}

class Vec2D(x:Double, y:Double) extends Vec[Dim2D.type](Array(x,y))
class Vec3D(x:Double, y:Double, z:Double) extends Vec[Dim3D.type](Array(x,y,z))

Of course it depends on how you want to represent the data, and if you want to have mutable or immutable instances. And for "real world" applications you should consider http://code.google.com/p/simplex3d/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...