如果你看一下这里的图像包http://golang.org/src/pkg/image/image.go,你会发现每个图像的Opaque()实现都是一样的,只是在像素特定的逻辑上不同。
这有什么理由吗?任何一般解决方案效率会降低吗?这只是一个疏忽吗?是否有一些限制(我看不到一个)类型系统会使多态[is:generic]方法变得困难?
[edit]我想到的那种解决方案(在Java意义上不需要泛型)就像:
type ColorPredicate func(c image.Color) bool;
func AllPixels (p *image.Image, q ColorPredicate) bool {
var r = p.Bounds()
if r.Empty() {
return true
}
for y := r.Min.Y; y < r.Max.Y; y++ {
for x := r.Min.X; x < r.Max.X; x++ {
if ! q(p.At(x,y)) {
return false
}
}
}
return true
}
但是我在编译时遇到了麻烦(对Go来说还是很新的 - 它会用图像编译,但不能用图像指针编译!)。
难以优化吗? (您需要具有函数内联,但是不会将任何类型检查从循环中拉出来吗?)。此外,我现在意识到我之前不应该使用“通用”这个词 - 我只是以通用(ha)的方式使用它。
答案 0 :(得分:4)
类型系统存在一个限制,它阻止了一般解决方案(或至少使效率非常低)。
例如,RGBA.Opaque和NRGBA.Opaque的主体是相同的,所以你认为它们可以被分解成第三个具有如下签名的函数:
func opaque(pix []Color, stride int, rect Rectangle) bool
您想以这种方式调用该函数:
func (p *RGBA) Opaque() bool {
return opaque([]Color(p.Pix), p.Stride, p.Rect)
}
但你不能。 p.Pix无法转换为[] Color,因为这些类型具有不同的内存表示形式,并且规范禁止它。我们可以分配一个新的切片,转换p.Pix的每个单独的元素,并传递它,但这将是非常低效的。
观察RGBAColor和NRGBAColor具有完全相同的结构。也许我们可以将这两种类型的函数分解出来,因为像素切片的内存中表示完全相同:
func opaque(pix []RGBAColor, stride int, rect Rectangle) bool
func (p *NRGBA) Opaque() bool {
return opaque([]RGBAColor(p.Pix), p.Stride, p.Rect)
}
唉,这是不允许的。这似乎更像是一个规范/语言问题,而不是技术问题。我确定之前已经在邮件列表中出现了,但我找不到对它的良好讨论。
这似乎是仿制药会派上用场的一个领域,但Go中还没有针对仿制药的解决方案。
答案 1 :(得分:1)
Why does Go not have generic types?
一些人可能会添加泛型 点。我们感到不紧急 他们,虽然我们了解一些 程序员做的。
泛型很方便,但它们来了 代价是复杂的类型 系统和运行时。我们还没有 找到了一种赋予价值的设计 与复杂性成比例, 虽然我们继续思考 它。同时,Go的内置地图和 切片,加上使用的能力 要构造的空接口 容器(带有显式拆箱) 在许多情况下意味着有可能 编写做泛型的代码 如果不太顺利,将会启用。
这仍然是一个悬而未决的问题。