我正在尝试构建一些图像代数代码,这些代码可以处理具有不同类型像素的图像(基本上是线性像素缓冲区+尺寸)。为了实现这一点,我已经定义了一个参数化的Pixel特性,其中有一些方法应该能够与任何Pixel子类一起使用。 (目前,我只对使用相同Pixel类型的操作感兴趣。)这是:
trait Pixel[T <: Pixel[T]] {
def div(v: Double): T
def div(v: T): T
}
现在我定义了一个基于三个双打(基本上是RGB 0.0-1.0)的存储的Pixel类型,我称之为TripleDoublePixel:
class TripleDoublePixel(v: Array[Double]) extends Pixel[TripleDoublePixel] {
var data: Array[Double] = v
def this() = this(Array(0.0, 0.0, 0.0))
def div(v: Double): TripleDoublePixel = {
new TripleDoublePixel(data.map(x => x / v))
}
def div(v: TripleDoublePixel): TripleDoublePixel = {
var tmp = new Array[Double](3)
tmp(0) = data(0) / v.data(0)
tmp(1) = data(1) / v.data(1)
tmp(2) = data(2) / v.data(2)
new TripleDoublePixel(tmp)
}
}
然后我们使用像素定义图像:
class Image[T](nsize: Array[Int], ndata: Array[T]) {
val size: Array[Int] = nsize
val data: Array[T] = ndata
def this(isize: Array[Int]) {
this(isize, new Array[T](isize(0) * isize(1)))
}
def this(img: Image[T]) {
this(img.size, new Array[T](img.size(0) * img.size(1)))
for (i <- 0 until img.data.size) {
data(i) = img.data(i)
}
}
}
(我想我应该能够在没有明确声明大小和数据的情况下使用,并且只使用默认构造函数中已经命名的内容,但我还没有这样做。)
现在我想编写代码来使用它,不必知道像素是什么类型。例如:
def idiv[T](a: Image[T], b: Image[T]) {
for (i <- 0 until a.data.size) {
a.data(i) = a.data(i).div(b.data(i))
}
}
不幸的是,这不会编译:
(fragment of lindet-gen.scala):145:
error: value div is not a member of T
a.data(i) = a.data(i).div(b.data(i))
我在#scala告诉我这对其他人有用,但那是2.8。我试图让2.8-rc1继续,但是RC1不能为我编译。有没有办法让它在2.7.7中工作?
答案 0 :(得分:5)
您的idiv
函数必须知道它实际上将使用像素。
def idiv[T <: Pixel[T]](a: Image[T], b: Image[T]) {
for (i <- 0 until a.data.size) {
a.data(i) = a.data(i).div(b.data(i))
}
}
普通类型参数T
将为所有可能的类型T
定义函数,当然这些函数并不都支持div
操作。因此,您必须设置一个通用约束,将可能的类型限制为Pixel
s。
(注意你也可以把这个约束放在Image
类上,假设一个不同于像素的图像没有意义)