Типы, зависящие от пути, против «базовых типов», какие из них проверяются? - PullRequest
3 голосов
/ 03 февраля 2011

При использовании зависимых от пути типов с отражением я получаю ошибку несоответствия типов, даже если у меня совпадают "базовые типы".Что это за «неосновные типы» и почему они проверяются вместо «базовых типов»?

В приведенном ниже коде я хочу, чтобы метод compare принимал только подклассы того же типа Aаргументы.Ошибка в последней строке.

abstract class A(val a:Int) {
  type Impl <: A
  def compare(other:Impl) {
    if(a==other.a) println("equal") else println("diff")
  }
}
class B(a:Int) extends A(a) {type Impl = B}

object Test {
  def newInst(a: Int, className: String) = {
    val constr = Class.forName(className).getConstructors()(0)
    constr.newInstance(a.asInstanceOf[AnyRef]).asInstanceOf[A]
  }

  def main(args: Array[String]) {
    val b1 = newInst(4, "B")
    val b2 = newInst(5, "B")
    b1.compare(b2)   // type mismatch error here
  }
}

В последней строке я получаю эту ошибку:

error: type mismatch;
found   : b2.type (with underlying type A)
required: b1.Impl

Поскольку тип b2 совпадает с типом b1 (которыйА), я ожидал, что это не приведет к ошибке.По некоторым причинам эти зависимые от пути типы отличаются от «базовых типов» при использовании отражения.Зачем?

Если я не использую отражение, оно работает:

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors

(мне нужно использовать отражение в моем случае).Может ли newInst() вернуть объект как класс "B", используя отражение?Это поможет?Есть ли стирание типов при использовании абстрактных типов?

Это единственная найденная мной ссылка ( на этом форуме ) о той же ошибке, но она может быть не связана.

Ответы [ 2 ]

5 голосов
/ 03 февраля 2011

Я тоже это понял. выражение "базовый тип" немного вводит в заблуждение, в то время как это на самом деле означает "родительский тип". В идеале я хотел бы приведите тип возврата newInst к класс "className", но это выглядит как это невозможно в Scala. «

Это не означает «родительский тип». Этот тип действительно является родителем. Базовый тип относится к расширению одноэлементного типа. Тип числа 5 - синглтон; его базовый тип - Int. Большинство людей не назвали бы Int «родительским типом». (Хотя, опять же, это так.)

Что касается вопроса, вы можете просто разыграть его. Ничто не встанет у вас на пути: scala не будет, а java не сможет.

def main(args: Array[String]) {
  val b1 = newInst(4, "B")
  val b2 = newInst(5, "B")
  b1.compare(b2.asInstanceOf[b1.Impl])
}
% scala Test
diff
5 голосов
/ 03 февраля 2011

Это не имеет ничего общего с отражением.Тип b1 и b2 равен A (поскольку это тип возврата newInst).Для вызова b1.compare(b2) для компиляции b2 должен иметь тип b1.Impl.Компилятор знает только, что это какой-то подтип A, но не знает, какой именно.Поскольку вы не можете передать A, где требуется некоторый подтип A, вы получите ошибку.

В примере

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors

обе переменные имеют тип Bи B#Impl равно B, так что все проверки типов.

...