代码之家  ›  专栏  ›  技术社区  ›  IttayD

避免在泛型方法中强制转换为Nothing

  •  4
  • IttayD  · 技术社区  · 16 年前
    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...
    

    如果“u”未被推断或显式设置为“real”类型,是否有方法写入foo以返回any?

    4 回复  |  直到 9 年前
        1
  •  7
  •   retronym    16 年前

    不,静态类型是 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
  •  2
  •   Ken Bloom    16 年前

    答案是,您需要始终使用 foo[String]("hi") . 因为泛型类型 U 没有出现在任何参数中,无法推断。

    无法将foo的泛型参数默认为 Any 当它不能被推断出来的时候(它永远不能被推断出来)。如果要将函数重新定义为

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

    那么以下调用将无法编译:

    val s:Any="Hi"
    foo[String](s) 
    
        3
  •  1
  •   Arjan Blokzijl    16 年前

    我不知道这是不是你的意思,但你不能用u来代替t吗?

    
    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
    
        4
  •  1
  •   Community Mohan Dere    9 年前

    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]
    

    这样,如果忘记添加类型参数,将得到编译时警告:

    f("123")  // Fails
    f[String]("123")  // OK