Как заставить Scala правильно разрешать эти абстрактные типы - PullRequest
1 голос
/ 17 февраля 2012

У меня возникли сложности при разработке решения для этой иерархии классов, которую я хочу собрать. У меня есть абстрактный пакет данных "Vertex" и абстрактный класс "VertexShader", который работает с экземплярами Vertex. Фактически производные классы от 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)
   }
}

1 Ответ

6 голосов
/ 17 февраля 2012

Проблема в том, что аннотации вашего типа отбрасывают информацию:

val mVShader : VertexShader = new MyVertexShader

Вы только что сказали, что это VertexShader - но по порядку чтобы перейти MyVertex к его методу затенения, вам нужно быть более конкретно:

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 { ... }

Вы можете получить конкретный T для AMesh как

AMesh#T

и для конкретного AMash объекта как

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

, хотя последний является хитрой вещью, которая не всегда работает или требует зависимых типов методов .

...