избегая приведения к Ничему в универсальном методе - PullRequest
4 голосов
/ 01 июля 2010
scala> def foo[U](t: Any) = t.asInstanceOf[U]
foo: [U](t: Any)U

scala> val s: String = foo("hi")

scala> val n = foo("hi")
java.lang.ClassCastException: java.lang.String cannot be cast to scala.runtime.Nothing$
    at .<init>(<console>:6)
    at .<clinit>(<console>)
    at RequestResult$.<init>(<console>:9)
    at RequestResult$.<clinit>(<console>)
    at RequestResult$scala_repl_result(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
    at scala.util.control.Exce...

Есть ли способ написать #foo так, чтобы он возвращал Any, если 'U' не выведено или явно установлено для "реального" типа?

Ответы [ 4 ]

7 голосов
/ 01 июля 2010

Нет.Статический тип U.Если это выводится как Nothing, компилятор не допустит возвращаемое значение типа Any.

. Вы можете улучшить сообщение об ошибке времени выполнения:

def foo[U: Manifest](t: Any): U = if (implicitly[Manifest[U]] == manifest[Nothing]) 
  error("type not provided") 
else t.asInstanceOf[U]

или выполнитьПредложение Арджана.

2 голосов
/ 31 декабря 2016

С здесь лучше исправить foo, чтобы он не мог быть вызван для возврата типа Nothing:

sealed trait NotNothing[-T] 

object NotNothing {
  implicit object YoureSupposedToSupplyAType extends NotNothing[Nothing]
  implicit object notNothing extends NotNothing[Any] 
}

def foo[U:NotNothing](t:U)=t.asInstanceOf[U]

Таким образом, если вы забудете добавить параметр типа, вы получите предупреждение во время компиляции:

f("123")  // Fails
f[String]("123")  // OK
2 голосов
/ 01 июля 2010

Ответ заключается в том, что вам нужно всегда указывать универсальный тип с помощью foo[String]("hi"). Поскольку универсальный тип U не указан ни в одном из параметров, он не может быть выведен.

Нет никакого способа установить для стандартного параметра foo значение по умолчанию Any, когда его нельзя вывести (что никогда не может быть выведено). Если вы переопределите функцию как

def foo[U](t:U)=t.asInstanceOf[U]

тогда следующий вызов не будет скомпилирован:

val s:Any="Hi"
foo[String](s) 
1 голос
/ 01 июля 2010

Я не уверен, что вы имеете в виду, но вы не можете просто использовать U как тип для t вместо Any?


scala> def foo[U](t: U) = t.asInstanceOf[U]         
foo: [U](t: U)U

scala> foo("hi")
res0: java.lang.String = hi

scala> foo(1)   
res1: Int = 1

scala> val a:Any = "hi" 
a: Any = hi

scala> foo(a)
res2: Any = hi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...