scala – 为什么`Some(123).isInstanceOf [Option [List [String
当使用.isInstanceOf [GenericType [SomeOtherType]],其中GenericType和SomeOtherType是任意类型(适合类型)时,Scala编译器由于类型擦除而提供未检查的警告:
scala> Some(123).isInstanceOf[Option[Int]] <console>:8: warning: non variable type-argument Int in type Option[Int] is unchecked since it is eliminated by erasure Some(123).isInstanceOf[Option[Int]] ^ res0: Boolean = true scala> Some(123).isInstanceOf[Option[String]] <console>:8: warning: non variable type-argument String in type Option[String] is unchecked since it is eliminated by erasure Some(123).isInstanceOf[Option[String]] ^ res1: Boolean = true 但是,如果SomeOtherType本身是通用类型(例如List [String]),则不会发出警告: scala> Some(123).isInstanceOf[Option[List[String]]] res2: Boolean = true scala> Some(123).isInstanceOf[Option[Option[Int]]] res3: Boolean = true scala> Some(123).isInstanceOf[Option[List[Int => String]]] res4: Boolean = true scala> Some(123).isInstanceOf[Option[(String,Double)]] res5: Boolean = true scala> Some(123).isInstanceOf[Option[String => Double]] res6: Boolean = true (回想起元组和=>是Tuple2 []和Function2 []通用类型的语法糖) 为什么不发出警告? (所有这些都在Scala REPL 2.9.1中,使用-unchecked选项.) 解决方法
我来看看Scala的编译器源码,我发现有趣的是看看
scala.tools.nsc.typechecker.Infer 这是你发现警告的地方.如果仔细观察第1399行: def checkCheckable(pos: Position,tp: Type,kind: String) 这是生成警告的地方,您会看到一些嵌套方法,包括检查方法: def check(tp: Type,bound: List[Symbol]) { def isLocalBinding(sym: Symbol) = sym.isAbstractType && ((bound contains sym) || sym.name == tpnme.WILDCARD || { val e = context.scope.lookupEntry(sym.name) (e ne null) && e.sym == sym && !e.sym.isTypeParameterOrSkolem && e.owner == context.scope }) tp match { case SingleType(pre,_) => check(pre,bound) case TypeRef(pre,sym,args) => if (sym.isAbstractType) { if (!isLocalBinding(sym)) patternWarning(tp,"abstract type ") } else if (sym.isAliasType) { check(tp.normalize,bound) } else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) { error(pos,"type "+tp+" cannot be used in a type pattern or isInstanceOf test") } else { for (arg <- args) { if (sym == ArrayClass) check(arg,bound) else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types else arg match { case TypeRef(_,_) if isLocalBinding(sym) => ; case _ => patternWarning(arg,"non variable type-argument ") } } } check(pre,bound) case RefinedType(parents,decls) => if (decls.isEmpty) for (p <- parents) check(p,bound) else patternWarning(tp,"refinement ") case ExistentialType(quantified,tp1) => check(tp1,bound ::: quantified) case ThisType(_) => ; case NoPrefix => ; case _ => patternWarning(tp,"type ") } } 虽然我不是Scala编译器的专家,但我们都应该感谢这些人,使代码如此自明.我们来看看tp匹配块和处理的病例: >如果是单一类型 >如果是抽象类型 如果您看到所有其他情况,还有一行也被评论: else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types 如果您的类型具有其他类型参数(如Function2或Tuple2),那么会告诉您会发生什么.检查功能返回单元,不执行任何测试. 我不是为什么这样做是以这种方式完成的,但是您可能想要打开一个错误 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |