【问题标题】:How do I get Scala to resolve these abstract types properly如何让 Scala 正确解析这些抽象类型
【发布时间】:2012-02-17 06:26:56
【问题描述】:

我在为我想要组装的这个类层次结构制定解决方案时遇到了困难。我有一个抽象数据包“Vertex”和一个在 Vertex 实例上运行的抽象类“VertexShader”。实际上,来自 VertexShader 的派生类对 Vertex 的特定派生类进行操作。这很像 def eat(f : Food) 的 Animal 类的经典示例,但其子类只能吃特定种类的食物。

我猜问题是派生的 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)
   }
}

【问题讨论】:

    标签: scala inheritance abstract-type


    【解决方案1】:

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

    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 AMash extends Mesh { ... }
    

    您可以将AMesh 的特定T 获取为

    AMesh#T
    

    对于特定的AMash 对象

    val amesh: AMesh = ...
    ... amesh.T ...
    

    虽然后者是一件棘手的事情,并不总是有效,或者需要dependent method types

    【讨论】:

    • 是的,这将修复示例,但在实际情况下,假设我有一个抽象类型 Mesh 的引用 (val),它具有如下函数:“def generateVertex : Vertex”当然,它返回一个特定类型的顶点 T
    猜你喜欢
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多