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

用于在自定义scala类上操作的实用程序方法,scala,oop,abstract-class,Scala,Oop,Abstract Class,我想在Scala中定义一个在自定义类上工作的操作符。与scala类似,例如数组串联: 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

我想在Scala中定义一个在自定义类上工作的操作符。与scala类似,例如数组串联:

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的函数,但我更愿意利用抽象类来要求抽象类的扩展提供一种方法来创建特定于该类的随机内容

使用第一个示例,为了能够调用操作符
concat
作为
Array.concat()
,需要在作用域中的某个地方存在一个名为
Array
的对象,该对象将
concat
作为方法。最简单的方法是:

object Array {
  def concat[T](xs: Array[T], ys: Array[T]): Array[T] = ...
}
否则,您可以定义一个抽象类(或trait)并让对象继承它:

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 {}
或者,抽象类可以只定义运算符,对象将实现它:

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] = ...
}

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

我们可以定义一个OpTrait,该OpTrait声明一个方法(“op”),该方法对相同类型的对象进行操作,因此实现该方法的任何类只能接受与其声明的类相同类型的参数

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


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

1。我很困惑。问题是什么。这三个代码示例似乎都非常不同,而且根本不相似。你的最后一句话准确地描述了你所做的事情。我假设你的意思是你想要第三个代码段的功能,以及第二个代码段的语法?看我的回答我给了你第一个的语法,第三个和第二个的组合功能。我的答案的最后两行看起来像你的前两行。这回答了前面提到的问题。我最终的实现略有不同,在不同的抽象类中定义了原始类的集合,类似于您的第一个建议。
trait OpTrait[B] {
    def op(b: B)
}

object MyClass {
    def op[A <: OpTrait[A]](x: A, y: A) = x.op(y) // x op y
}
// 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)