我想定义一个在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的函数,但我宁愿利用抽象类来强要求抽象类的扩展提供一个方法来创建特定于那个班级。
答案 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的子类型,但仅当参数在一个顺序中时才能定义。