我目前正在考虑重构我的个人线性代数包。 真正困扰我的一件事是:
目前我只支持由float
组成的向量和矩阵。现在,我想添加对int
,double
的支持,甚至可能支持boolean
,但我不得不考虑这一点。
有一件事:我不想多次编写代码。事实上,这是我在编程中真正讨厌的一件事。我想要一个特定代码/行为的单一责任来源。
对于大多数人来说,所有操作,Vector都有一定的模式。如果我添加两个保持int
s或float
s的二维向量并不重要,操作总是相同的。
现在,天真地我虽然"嗯,这有多难?!"事实证明,对于我来说,作为Scala-noobie,它并不那么容易。
我开始时:
trait Vector[Vec <: Vector]
{
def add(v: Vec): Unit
def subtract(v: Vec): Unit
def multiply(v: Vec): Unit
def multiply(s: Numeric): Unit
def dot(v: Vec): Numeric
def length(): Numeric
def distance(v: Vec): Numeric
def normalise(): Unit
def divide(length: Numeric): Unit
def toArray(): Array[Numeric]
}
我的想法:当我继续时,添加一个界限会帮助我。
示例:
abstract class Vector2(var x: Numeric, var y: Numeric) extends Vector[Vector2]
{
override def add(v: Vector2): Unit =
{
this.x += v.x
this.y += v.y
}
//...
}
然后我想创建像:
这样的子类型class IntVector2(var x: Int, var y: Int) extends Vector2
并完成它。
问题从这里开始:
abstract class Vector2(var x: Numeric, var y: Numeric) extends Vector[Vector2]
{
override def add(v: Vector2): Unit =
{
this.x += v.x // **here is the problem **
this.y += v.y
}
//...
}
它说
类型不匹配,预期:字符串,实际:数字
我认为通过使用数字作为上限我是聪明的,因为我认为所有人都会定义一个补充...我有多错?
我该如何解决这个问题?有什么想法吗?
另外,在我忘记之前...
假设我需要使用帮助器的情况,例如math.sqrt(...)
。该怎么办?
目前(仅针对float
实施,请注意!)我这样做:
def length(): Float =
{
math.sqrt(x * x + y * y).toFloat
}
现在,如果我想为double
和int
提供相同的内容,我该如何制作此通用内容?比如,没有.toFloat
另外,我完全清楚boolean
我会遇到问题,因为有些操作根本就没有定义......没有理由害怕,我希望:)
答案 0 :(得分:1)
你应该考虑查看scala标准集合库。注意所有以 Like 结尾的类:TraversableLike,SeqLike,SetLike等。他们使用higher-order types和typeclass polymorphism。注意所有对def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That
等方法的隐式参数的使用。
Here是提供许多数字抽象的项目,可以用作参考。