如何让Scala正确地解析这些抽象类型

12 浏览
0 Comments

如何让Scala正确地解析这些抽象类型

我在构建这个类层次结构时遇到了困难。我有一个抽象数据包"Vertex"和一个操作Vertex实例的抽象类"VertexShader"。实际上,从VertexShader派生的类操作特定派生类的Vertex。这很像经典的Animal类示例,它有一个"def eat(f : Food)"方法,但是它的子类只能吃特定类型的食物。

问题在于派生的Vertex类应该提供一个"+"函数,可以对顶点进行操作,并且我需要将此操作的结果传递给VertexShader。问题在于,即使类型通过推断正确解析,系统也不允许我将"+"操作的结果传递给VertexShader对象。

非常欢迎任何关于如何重新设计以避免类型问题的建议。

抽象接口类型:

trait Vertex {

type V <: Vertex

def position: Float

def + (v: V): V

}

派生的顶点着色器类将使用特定派生类的顶点进行着色:

trait VertexShader {

type V <: Vertex

def shade(v: V): Float

}

具体的实现示例:

class MyVertex(p: Float, c: Float) extends Vertex {

type V = MyVertex

val position: Float = p

val color: Float = p * 2.0f

def + (v: MyVertex): MyVertex = new MyVertex(position + v.position, color + v.color)

}

class MyVertexShader extends VertexShader {

type V = MyVertex

def shade(v: MyVertex): Float = v.position + v.color

}

对象Bootstrap:

def main(args: Array[String]) {

// 顶点和顶点着色器,假设具体类类型在运行时从其他抽象对象接口中获取

val mVShader: VertexShader = new MyVertexShader

val mV0: Vertex = new MyVertex(1.0f, 9.0f)

val shadeValue = mVShader.shade(mV0 + mV0)

}

0
0 Comments

问题的出现原因是类型注解丢失了信息。在代码中,通过声明val mVShader : VertexShader = new MyVertexShader,仅仅指定了它是一个VertexShader类型,但是为了将MyVertex传递给它的shade方法,需要更加具体地指定类型。val mVShader : VertexShader {type V = MyVertex} = new MyVertexShader可以实现这个目的。

最简单和简洁的解决方法是移除类型注解:

val mVShader = new MyVertexShader
val mV0 = new MyVertex(1.0f, 9.0f)

对于你的评论的回答:

如果有这样的代码:

trait Mesh {
    trait T <: Vertex
    def getVertex: T
}

class AMesh extends Mesh { ... }

你可以通过AMesh#T获得AMesh的具体类型T,对于特定的AMash对象,可以使用val amesh: AMesh = ...

... amesh.T ...,但这是一个棘手的问题,不一定总能正常工作,或者需要使用dependent method types

是的,这将解决这个示例问题,但在实际情况下,假设我有一个抽象类型为Mesh的引用(val),它有一个函数"def generateVertex : Vertex",当然它返回一个特定类型T < Vertex的顶点。我能从这个Mesh对象获取这个类型信息吗?例如,如果类Mesh声明了"type V < Vertex",我可以说Mesh.V吗?

0