Можем ли мы вывести общий тип вывода? - PullRequest
1 голос
/ 12 октября 2011

Рассмотрим следующий код Scala

def NOTImplementedIn[T<: AnyRef](t:T):String = 
  throw new Exception(t.getClass.getName+": Input type not implemented")

def NOTImplementedOut[T<: AnyRef](s:String):T = 
  throw new Exception("Output type not implemented")

В первом случае можно вывести тип ввода T.Есть ли способ вывести тип вывода T во втором случае?Я хотел бы включить имя типа в исключение.

Ответы [ 2 ]

4 голосов
/ 12 октября 2011

Нижняя граница типа T всегда будет выведена. Если явно не задана нижняя граница типа, ничто не является границей.

Этот вывод является правильным. Поскольку общий тип параметра стирается во время выполнения, вызовы f[String]("foo"), f[File]("foo") и f[List[Int]]("foo") и f[Nothing]("foo") - это один и тот же вызов f("foo") во время выполнения. Результат должен быть действительным String, File, List[Int] и Nothing. Быть Nothing - единственный способ удовлетворить это (что означает, что результата не будет). Если бы была более сильная нижняя граница типа, она должна была бы быть только этого типа.

Следствием этого является то, что подпрограмма f[T >: LowerBound](parameters): T,, где T не появляется в parameters, ничем не отличается от f(parameters): LowerBound, и нет смысла делать ее родовой (когда LowerBound не указано явно, граница типа Nothing)

С той же идеей, что вызов f[T]("foo") только f("foo") во время выполнения, ясно, что имя не может появиться в сообщении об исключении. Таким образом, T должен быть каким-то образом пропущен во время выполнения, и манифесты являются обычным способом сделать это, как отметил Дейв. Теперь T появляется в параметрах, и все по-другому. если кто-то вызывает f[File]("foo"), компилятор преобразует это в f("foo")(manifest_of_file), где manifest_of_file позволяет, среди прочего, получить имя типа File.

Это все еще не вывод, поскольку File было написано явно. Единственный способ определить тип T - это от ожидаемого типа вызова к f в контексте. Если кто-то делает val file: File = f("foo") или передает f("foo") значение параметра типа File в какую-либо подпрограмму или просто пишет f("foo"): File, будет ли File выводиться? Нет не будет Еще раз, Nothing будет выведено. Причина в том, что это более точный тип, чем File, и поскольку компилятор может передавать либо Manifest [File], либо Manifest [Nothing] (и любой другой тип между ними), он выбирает более точный. Это может быть удивительно для Nothing, но предположим, что ваша нижняя граница типа String, а ожидаемый тип просто AnyRef, нет очевидной причины выбирать AnyRef, а не более String.

def f[T >: String : Manifest](s: String): T = "type is " + manifest[T].toString
val x: AnyRef = f("foo"): AnyRef
x: Anyref = type is java.lang.String

То же самое с вашим примером и Nothing как нижняя граница типа:

def g[T: Manifest](s: String): T = throw new Exception("type is " + manifest[T])
val y: String  = g("foo"): String
java.lang.Exception: type is Nothing
        at .g(<console>:7)
        ....
3 голосов
/ 12 октября 2011

Да, используя Manifest.

def NOTImplementedOut[T<: AnyRef](s:String)(implicit m: scala.reflect.Manifest[T]):T =
  throw new Exception(m.toString + ": Output type not implemented")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...