用于操作自定义scala类的实用程序方法

时间:2014-08-19 02:04:09

标签: scala oop abstract-class

我想定义一个在Scala中处理自定义类的运算符。与scala的Array utility methods类似,例如Array concatenation:

val (a, b) = (new Array[Int](4), new Array[Int](3))
val c = Array.concat(a, b)

我想模糊地定义一个运算符如下:

class MyClass {
  def op():MyClass = {
     // for instance,, 
     return new MyClass();
  }
}

要调用,比如 val x = MyClass.op()

为了提供更具体的示例,假设MyClass是MyAbstractClass的扩展

// Provided as a utility for the more relevant code below. 
def randomBoolean():Boolean = {
  val randomInt = Math.round(Math.random()).toInt
  if (randomInt == 1 ) return true;
  else return false;
}

abstract class MyAbstractClass[T](size:Int) {
  val stuff = new Array[T](size)
  def randomClassStuff():Array[T]
}

class MyClass(size:Int) extends MyAbstractClass[Boolean](size) {
  def randomClassStuff():Array[Boolean] = {
    return new Array[Boolean](size) map {x => randomBoolean()}
  } 
}

我意识到我可以定义一个名为MyClass的对象,其中定义了一个名为randomClassStuff的函数,但我宁愿利用抽象类来强要求抽象类的扩展提​​供一个方法来创建特定于那个班级

2 个答案:

答案 0 :(得分:0)

使用您的第一个示例,为了能够将concat调用为Array.concat(),需要在Array范围内存在一个名为concat的对象,其范围为object Array { def concat[T](xs: Array[T], ys: Array[T]): Array[T] = ... } 一个方法。最简单的方法是:

abstract class ArrayUtils {
  // Implemented here
  def concat[T](xs: Array[T], ys: Array[T]): Array[T] = ...
}

//Define the object
object Arrays extends ArrayUtils

// Or as a val
val Array = new ArrayUtils {}

否则你可以定义一个抽象类(或trait)并让对象继承它:

abstract class ArrayUtils {
  // Defined here
  def concat[T](xs: Array[T], ys: Array[T]): Array[T]
}

object Arrays extends ArrayUtils {
  // Implemented here
  def concat[T](xs: Array[T], ys: Array[T]): Array[T] = ...
}

或者,抽象类可以只定义运算符,对象将实现它:

{{1}}

最后一个可能与你想要的最接近。

答案 1 :(得分:0)

我们可以定义一个声明一个方法(" op")的OpTrait,它对相同类型的东西进行操作,这样任何实现该方法的类只能接受与该方法相同类型的参数。它被宣布为。

然后,我们可以定义一个对象,它接受任何两个相同类型的对象,只要它们包含" op"方法(通过在OpTrait中混合 - 您也可以使用结构类型,但速度慢且组织性较差):

trait OpTrait[B] {
    def op(b: B)
}

object MyClass {
    def op[A <: OpTrait[A]](x: A, y: A) = x.op(y) // x op y
}

现在我们可以创建任何扩展OpTrait和类MyClass.op(obj1,obj2)的类:

// example of usage
class MyClass(val num: Int) extends OpTrait[MyClass] {
    def op(b: MyClass) = new MyClass(num + b.num)
}

val (a,b) = (new MyClass(5), new MyClass(6))
MyClass.op(a, b) // should return MyClass(11)

由于OpTrait是在泛型类型上参数化的,因此您可以实际定义不同类型之间的操作(但只能在一个订单中)。您还可以通过使其变为协变来定义要在MyClass上工作的操作和MyClass的子类型,但仅当参数在一个顺序中时才能定义。