Проблема типа, зависящая от абстрактного пути Scala

Кто-нибудь знает, что здесь происходит с этой ошибкой компилятора? Ошибка исчезает, если я не расширяю INode.

trait AbsTypes
{
    type TKey
    type TValue
}

trait INode extends AbsTypes
{
    def get(key : TKey) : TValue
    def set(key : TKey, v : TValue) : INode
}

class ANode[TKey,TValue](
  val akey : TKey,
  val aval : TValue
) extends INode
{
    // ERROR : type mismatch;  found   : ANode.this.aval.type (with underlying type TValue)  required: ANode.this.TValue
    def get(key : TKey) : TValue = { aval }
    def set(key : TKey, v : TValue) : INode = {
        new ANode(key,v)
    }
}

person ACyclic    schedule 25.07.2010    source источник


Ответы (2)


Универсальные параметры не переопределяют автоматически абстрактные типы, даже если они имеют одинаковые имена. Попробуйте переименовать универсальные параметры (во избежание конфликтов имен), а затем объявить типы TKey и TValue в теле метода.

class ANode[A,B](
  val akey : A,
  val aval : B
) extends INode {
    type TKey=A
    type TValue=B
    def get(key : TKey) : TValue =  aval 
    def set(key : TKey, v : TValue) : INode = new ANode(key,v)
}

Я полагаю, было бы неплохо, если бы компилятор выдал ошибку в строке, где вы указали имена универсальных типов, вместо того, чтобы ждать, пока вы начнете использовать эти типы.

person Ken Bloom    schedule 26.07.2010
comment
Спасибо, это решило эту часть, но у меня есть дополнительный вопрос, который я опубликую отдельно. - person ACyclic; 26.07.2010
comment
Возможно, стоит добавить сюда stackoverflow.com/questions/1332574/ - person oluies; 26.07.2010

К сожалению, у меня нет времени проверять то, что я собираюсь написать, но я понимаю ваш код так, что каждый INode получит свой собственный тип TValue. Таким образом, операция получения действительно возвращает INode.this.TValue, который несовместим с другим типом TValue на другом узле.

Способ избежать этого может состоять в том, чтобы написать:

trait Nodes {
  type TKey
  type TValue

  trait INode {
   def get(key : TKey) : TValue
  }

  class ANode(
    val akey : TKey,
    val aval : TValue
  ) extends INode
}
person Eric    schedule 26.07.2010
comment
У него все еще будет та же проблема с вашим кодом, потому что akey и aval относятся к типам, названным дженериками, а не абстрактными типами. (Более того, если вы скомпилируете только этот код, вы не заметите никаких ошибок компилятора, потому что вы не пытались использовать конфликтующие типы.) - person Ken Bloom; 26.07.2010
comment
О, да, это ошибка копирования и вставки. Мое намерение состояло в том, чтобы использовать типы из трейта Nodes. - person Eric; 26.07.2010
comment
Я отредактировал ваш ответ, чтобы отразить это намерение, и удалил свой отрицательный голос. - person Ken Bloom; 26.07.2010
comment
Спасибо, это сработает, но добавляет нежелательную ссылку на внешний тип в экземпляре моего узла. Я пытаюсь сделать узел как можно меньше/эффективнее - person ACyclic; 26.07.2010