В выводе типа Scala не учитывается, что эти типы идентичны, какими бы они ни были

У меня есть шаблон проектирования, в котором есть генератор объекта (MorselGenerator и его дочерние элементы), любой экземпляр которого всегда генерирует один и тот же точный тип объекта (Morsels и его дочерние объекты), но средство проверки типов не позволяет мне выполнять какие-либо операции с двумя или более из этих сгенерированных объектов, полагая, что они могут быть разными.

Как пройти проверку типов?

trait Morsel 
{ 
   type M <: Morsel
   def calories : Float 
   def + (v : M) : M
}

trait MorselGenerator
{
   type Mg <: Morsel
   def generateMorsel : Mg
}

class HotDog(c : Float, l : Float, w : Float) extends Morsel
{
   type M = HotDog   
   val calories : Float = c
   val length   : Float = l       
   val width    : Float = w
   def + (v : HotDog) : HotDog = new HotDog(v.calories + calories, v.length + length, v.width + width)
}

class HotDogGenerator extends MorselGenerator
{
   type Mg = HotDog
   def generateMorsel : HotDog = new HotDog(500.0f, 3.14159f, 445.1f)
}

object Factory
{
   def main ( args : Array[String] )
   {
      val hdGen = new HotDogGenerator()
      println(eatTwo(hdGen))
   }

   def eatTwo ( mGen : MorselGenerator )
   {
      val v0 : mGen.Mg = mGen.generateMorsel
      val v1 : mGen.Mg = mGen.generateMorsel
      v0 + v1                          /// ERROR HERE
   }
}

Компилятор выдает следующую ошибку компиляции

Generator.scala:43: error: type mismatch;  
found   : v1.type (with underlying type mGen.Mg)  
required: v0.M
      v0 + v1                          /// ERROR HERE
           ^ one error found


Обновление

Вот код C ++, более или менее эквивалентный тому, что я пытаюсь сделать. Обратите внимание, что функция eatTwo полностью полиморфна и не ссылается на определенные производные типы Morsel или MorselGenerator.

#include <stdlib.h>
#include <stdio.h>

template <class M> class Morsel
{
public:
   Morsel(float c) : calories(c) {}
   float calories;
   virtual M operator + (const M& rhs) const = 0;
};

template <class M> class MorselGenerator
{
public:
   virtual M * generateMorsel() const = 0;
};

class HotDog : public Morsel<HotDog>
{
public:
   HotDog(float c, float l, float w) : Morsel<HotDog>(c), length(l), width(w) {}
   float length, width;

   HotDog operator + (const HotDog& rhs) const 
   { return HotDog(calories+rhs.calories, length+rhs.length, width+rhs.width); }
};

class HotDogGenerator : public MorselGenerator<HotDog>
{
   HotDog * generateMorsel() const { return new HotDog(500.0f, 3.14159f, 445.1f); }
};

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

template <class MorselType> float eatTwo ( const MorselGenerator<MorselType>& mGen)
{
   MorselType * m0 = mGen.generateMorsel();
   MorselType * m1 = mGen.generateMorsel();
   float sum = ((*m0) + (*m1)).calories;
   delete m0; delete m1;
   return sum;
}

int main()
{
   MorselGenerator<HotDog> * morselStream = new HotDogGenerator();
   printf("Calories Ingested: %.2f\n", eatTwo(*morselStream));
   delete morselStream;
}
6
задан Fooberman 18 February 2012 в 22:43
поделиться