scala – 类型变量的类型模式的用例和示例
我发现阅读规范
scala支持绑定类型变量做一个类型模式匹配:
Map(1 -> "one",2 -> "two") match { case l: Map[k,v] => // binds k to Int and v to String // k and v are types as shown here: val i: Iterator[Tuple2[k,v]] = l.iterator println(i.mkString(",")) } 有没有什么花哨的事情或实际的事情我可以做到这一点?或绑定类型变量仅对类型文档目的有用吗? 对我来说,Scala有时候需要类型注释,例如定义函数,所以我试过: def prepender(obj: Any) = obj match { case xs: List[a] => (x: a) => x :: xs case opt: Some[a] => (x: a) => x :: Nil } 但是返回函数的类型是奇怪的: prepender: (obj: Any)a with a => List[Any] forSome { type a; type a } scala> val p = prepender(List(1,2)) p: a with a => List[Any] forSome { type a; type a } = <function1> scala> p(1) <console>:10: error: type mismatch; found : Int(1) required: a(in value res7) with (some other)a(in value res7) where type (some other)a(in value res7),type a(in value res7) 解决方法
我希望这不会太长,但是我真的很怀疑,这就是为什么我会先尝试提供一个快速的答案:“当你命名(抽象)某些东西时,主要的用例是在以后提及”.那现在没有帮助,是吗?
考虑这个简单的Scala功能: val sum = (a: Int,b: Int) => a + b 编译器不需要知道a是a,b是b.所有它需要知道一个以及b是类型Int和一个来到b之前(在这种情况下,这是没有关系的,因为添加是可交换的,但编译器关心!). Scala提供了一个(不要误会我也喜欢它)编译器友好的占位符语法,作为这个“假设”的证明. val sum: (Int,Int) => Int = _ + _ // where the 1st _ differs from the 2nd _ 现在看看这个: case x: SomeTypeParameterizedWith[AnotherType] // AnotherType is erased anyway case x: SomeParameterizedType[_] // Existential type case x: SomeParameterizedType[kind] // Existential type which you can reference 当您不关心类型参数时,请使用占位符语法.当你做(无论什么原因)时,请注意你应该用小写命名为type参数,以便编译器知道你想把它当作一个标识符. 回到你的问题 存在类型的主要用途是围绕Java的通配符类型. // This is a Java class with wildcards public class Wild { public java.util.Collection<?> contents() { java.util.Collection<String> stuff = new Vector<String>(); stuff.add("a"); stuff.add("b"); stuff.add("see"); return stuff; } } // This is the problem import scala.collection.mutable.Set val iter = (new Wild).contents.iterator val set = Set.empty[???] // what type goes here? while (iter.hasMore) set += iter.next() // This is the solution def javaSet2ScalaSet[T](jset: java.util.Collection[T]): Set[T] = { val sset = Set.empty[T] // now T can be named! val iter = jset.iterator while (iter.hasNext) sset += iter.next() sset } 好的,那刚才发生了什么?简单的泛型,没有魔法吗?如果您是日常处理仿制药,这对您来说看起来是正常的,但您忘记了将范围引入范围的超级概念仅适用于类和方法.如果你在一个班级或一个方法之外,只是在无处不在的随机范围(如REPL)怎么办?或者如果你在一个类或一个方法,但是类型参数还没有被引入其范围呢?这是你的问题和这个答案来的地方. val set = new Wild().contents match { case jset: java.util.Collection[kind] => { val sset = Set.empty[kind] val iter = jset.iterator while (iter.hasNext) sset += iter.next() sset } } 标识符类型是必需的,因此编译器可以验证您是指同一件事. 注意,您不能只是将字符串添加到集合中,因为集合的类型为Set [_]. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |