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'没有被推断或明确设置为“真实”类型?
答案 0 :(得分:7)
没有。静态类型为U
。如果将其推断为Nothing
,则编译器将不允许返回值Any
的值。
您可以改进运行时错误消息:
def foo[U: Manifest](t: Any): U = if (implicitly[Manifest[U]] == manifest[Nothing])
error("type not provided")
else t.asInstanceOf[U]
或遵循Arjan的建议。
答案 1 :(得分:2)
答案是您需要始终使用foo[String]("hi")
指定泛型类型。由于泛型类型U
未出现在任何参数中,因此无法推断出它。
无法推断foo的通用参数默认为Any
(永远不会推断它永远不会被推断)。如果您要将该功能重新定义为
def foo[U](t:U)=t.asInstanceOf[U]
然后以下调用将无法编译:
val s:Any="Hi"
foo[String](s)
答案 2 :(得分:2)
从here更好地修复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]
这样,如果您忘记添加type参数,您将收到编译时警告:
f("123") // Fails
f[String]("123") // OK
答案 3 :(得分:1)
我不确定这是不是你的意思,但你不能只用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