3

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

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

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», используя отражение? Это поможет? Существует ли стирание типа при использовании абстрактных типов?

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

+0

Благодарим за вопрос! Это было действительно странно и взяло меня на день, чтобы найти обходной путь и, наконец, увидел ваш пост. –

ответ

5

Это не имеет никакого отношения к отражению. Тип 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, так что все typechecks.

+0

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

5

I just figured that out too. The expression "underlying type" is a bit misleading, while it actually means "parent type". Ideally I would like to cast the return type of newInst to the class of "className" but that looks like it is not possible in 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 
+0

Что я имел в виду - это вернуть возвращаемое значение до его возврата, внутри newInst(). Поскольку у меня нет доступных типов (у меня есть только класс), я не вижу способа сделать это.Если бы это было возможно, средство проверки типов могло бы вывести тип newInst() во время компиляции на основе значения времени выполнения (className) - это, конечно, невозможно. Я думаю, что это также разъясняет значение «базового типа». Это наиболее специфический тип, известный во время компиляции, тогда как тип выполнения известен только как object.type. Я не уверен, что вы подразумеваете под «расширением singleton». b2 не является одиночным. – Adrian

+1

b2 абсолютно одноэлементный. Как вы думаете, что означает «b2.type»? Это тип b2. Не тип b1, b3 или что-либо еще в мире. И его базовый тип, каким он является экземпляром, равен A. – extempore

+0

b2 - это экземпляр B, отбрасываемый в A. Это не синглтон, который в моей книге (PinS) является объектом, определенным с ключевым словом 'object' , Что мне здесь не хватает? – Adrian

Смежные вопросы