只实现一次抽象行为......作为契约的特征,作为具体帮助者的抽象类

时间:2015-10-18 07:44:19

标签: scala generics abstraction generic-programming traits

我目前正在考虑重构我的个人线性代数包。 真正困扰我的一件事是:

目前我只支持由float组成的向量和矩阵。现在,我想添加对intdouble的支持,甚至可能支持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
}

现在,如果我想为doubleint提供相同的内容,我该如何制作此通用内容?比如,没有.toFloat

另外,我完全清楚boolean我会遇到问题,因为有些操作根本就没有定义......没有理由害怕,我希望:)

1 个答案:

答案 0 :(得分:1)

你应该考虑查看scala标准集合库。注意所有以 Like 结尾的类:TraversableLike,SeqLike,SetLike等。他们使用higher-order typestypeclass polymorphism。注意所有对def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That等方法的隐式参数的使用。

Here是提供许多数字抽象的项目,可以用作参考。