Двойное определение Scala (2 метода имеют стирание одного типа) - PullRequest
65 голосов
/ 22 июля 2010

Я написал это в Scala, и он не будет компилироваться:

class TestDoubleDef{
  def foo(p:List[String]) = {}
  def foo(p:List[Int]) = {}
}

уведомление компилятора:

[error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit

Я знаю, что JVM не имеет встроенной поддержки обобщений, поэтому я понимаю этоошибка.

Я мог бы написать оболочки для List[String] и List[Int], но я ленивый:)

Я сомневаюсь, но есть ли другой способ выразить List[String] это нетого же типа, что и List[Int]?

Спасибо.

Ответы [ 11 ]

0 голосов
/ 14 февраля 2011

Я не проверял это, но почему не сработала верхняя граница?

def foo[T <: String](s: List[T]) { println("Strings: " + s) }
def foo[T <: Int](i: List[T]) { println("Ints: " + i) }

Изменился ли перевод стирания с foo (List [Any]) дважды на foo (List[String] s) и foo (List [Int] i):

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ108

Мне кажется, я прочитал, что в версии 2.8 верхние границы теперь кодируются таким образом, а невсегда Any.

Чтобы перегружать ковариантные типы, используйте инвариантную границу (есть ли такой синтаксис в Scala? ... ах я думаю, что нет, но возьмем следующее в качестве концептуального дополнения к основномурешение выше):

def foo[T : String](s: List[T]) { println("Strings: " + s) }
def foo[T : String2](s: List[T]) { println("String2s: " + s) }

тогда я предполагаю, что неявное приведение исключено в стертой версии кода.


ОБНОВЛЕНИЕ: Проблема в том, что JVM стирает больше информации о типеМетод подписей, чем «необходимо».Я предоставил ссылку.Он удаляет переменные типа из конструкторов типов, даже конкретную границу этих переменных типов.Существует концептуальное различие, потому что нет никакого концептуального нереализованного преимущества для стирания границы типа функции, как это известно во время компиляции и не зависит от какого-либо экземпляра универсального, и для вызывающих абонентов необходимо не вызыватьфункция с типами, которые не соответствуют ограничению типа, так как же JVM может принудительно установить ограничение типа, если оно стерто?Хорошо одна ссылка говорит, что граница типа сохраняется в метаданных, к которым должны обращаться компиляторы.И это объясняет, почему использование границ типов не допускает перегрузки.Это также означает, что JVM - это широко открытая дыра в безопасности, поскольку ограниченные по типу методы могут вызываться без ограничений по типу (yikes!), Поэтому извините за то, что разработчики JVM не сделали бы такой небезопасной вещи.

ВВ то время, когда я писал это, я не понимал, что stackoverflow - это система оценки людей по качеству ответов, как, например, конкуренция за репутацию.Я думал, что это место для обмена информацией.В то время, когда я писал это, я сравнивал reified и non-reified с концептуального уровня (сравнивая много разных языков), и поэтому, по моему мнению, не имело смысла стирать границу типа.

...