2012-02-17 47 views
1

我很難爲我要組裝的這個類層次結構制定解決方案。我有一個抽象數據包「Vertex」,以及一個在Vertex實例上運行的抽象類「VertexShader」。實際上,VertexShader的派生類對Vertex的特定派生類進行操作。這很像經典的def eat(f : Food)動物類的例子,但其兒童班只能吃特定種類的食物。如何讓Scala正確解析這些抽象類型

我想問題是,派生頂點類應該提供一個函數「+」在頂點上運行,我需要將此操作的結果傳遞到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) 
    } 
} 

回答

6

的問題是,你的類型註釋丟棄信息:

val mVShader : VertexShader = new MyVertexShader 

你剛纔說的,這是一個VertexShader - 但爲了 沿MyVertex到它的樹蔭方法傳遞,你需要更具體 :

val mVShader : VertexShader {type V = MyVertex} = new MyVertexShader 

最簡單和concisest解決方法是刪除類型annotati附件:

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

針對您的評論:

如果你有

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

class AMash extends Mesh { ... } 

你可以得到特定TAMesh

AMesh#T 

和特定AMash對象

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

儘管後者是並不總是可行的,或者需要dependent method types一件棘手的事情。

+0

是的,這將修復這個例子,但在現實世界的情況下,假設我有一個抽象類型Mesh的引用(val),它有一個像這樣的函數:「def generateVertex:Vertex」,當然它返回特定類型T <頂點的頂點。我可以從這個Mesh對象獲得這個類型的信息嗎?例如,如果Mesh類聲明「type V Fooberman 2012-02-17 07:53:05