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

Foo*_*man 1 inheritance scala abstract-type

我很难为这个我要组装的类层次结构制作解决方案.我有一个抽象的数据包"Vertex",以及一个在Vertex实例上运行的抽象类"VertexShader".事实上,VertexShader的派生类在特定的Vertex派生类上运行.它很像Animal类的经典例子def eat(f : Food),但是它的子类只能吃特定种类的食物.

我想问题是派生的Vertex类应该提供一个对顶点进行操作的函数"+",我需要将这个操作的结果传递给VertexShader.问题是系统不允许我将'+'操作的结果传递给VertexShader对象,即使这些类型都通过推理正确解析.

有关如何重新设计以避免类型问题的任何建议都非常受欢迎.

/// Abstract Interface Types

trait Vertex 
{ 
   type V <: Vertex
   def position : Float 
   def + (v : V) : V
}

/// Derived class of vertex shader will use a specific derived class of
/// vertex that it can shade
trait VertexShader
{
   type V <: Vertex
   def shade( v : V ) : Float
}

/// Concrete Implementation Example

class MyVertex(p : Float, c : Float) extends Vertex
{
   type V = MyVertex   
   val position : Float = p       // inherited 
   val color    : Float = p*2.0f  // custom  

   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
}


object Bootstrap
{
   def main ( args : Array[String] )
   {
      /// Vertex and vertex shader, pretend concrete class type is unknown
      /// as these objects will be pulled out of some other abstract object
      /// interface at runtime
      val mVShader : VertexShader = new MyVertexShader
      val mV0 : Vertex = new MyVertex(1.0f, 9.0f)

     /////////////////////////////////////////

      val shadeValue = mVShader.shade(mV0 + mV0)
   }
}
Run Code Online (Sandbox Code Playgroud)

Owe*_*wen 6

问题是您的类型注释正在丢弃信息:

val mVShader : VertexShader = new MyVertexShader
Run Code Online (Sandbox Code Playgroud)

你刚才说它是VertexShader- 但为了传递MyVertex它的阴影方法,你需要更具体:

val mVShader : VertexShader {type V = MyVertex} = new MyVertexShader
Run Code Online (Sandbox Code Playgroud)

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

val mVShader = new MyVertexShader
val mV0 = new MyVertex(1.0f, 9.0f)
Run Code Online (Sandbox Code Playgroud)

回应你的评论:

如果你有

trait Mesh {
    trait T <: Vertex
    def getVertex: T
}
Run Code Online (Sandbox Code Playgroud)

class AMash extends Mesh { ... }
Run Code Online (Sandbox Code Playgroud)

你可以得到具体TAMeshas

AMesh#T
Run Code Online (Sandbox Code Playgroud)

对于特定的AMash对象

val amesh: AMesh = ...
... amesh.T ...
Run Code Online (Sandbox Code Playgroud)

虽然后者是一个棘手的事情,并不总是有效,或需要依赖的方法类型.