2012-02-17 26 views
1

私は組み立てたいこのクラス階層に対する解決策を作るのが難しいです。私は、抽象的なデータパケット "Vertex"と、Vertexインスタンスで動作する抽象クラス "VertexShader"を持っています。実際、VertexShaderの派生クラスはVertexの特定の派生クラスで動作します。 def eat(f : Food)のAnimalクラスの古典的な例によく似ていますが、その子クラスは特定の種類の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) 
    } 
} 

答えて

6

問題は、あなたのタイプの注釈が情報を破棄していることです:あなたはちょうどそれがVertexShaderであることを言った

val mVShader : VertexShader = new MyVertexShader 

- 、その陰メソッドに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 { ... } 

をお持ちの場合は

あなたは

として AMeshのための具体的な Tを得ることができます

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

として

AMesh#T 

特にAMashオブジェクトに対する後者は常に動作、またはdependent method typesを必要としないであろうトリッキーなものですが。

+0

実際の例では、実際のケースでは、「def generateVertex:Vertex」のような関数を持つ抽象型Meshの参照(val)があるとします特定のタイプT Fooberman

関連する問題