当前位置:K88软件开发文章中心编程语言SQLscala → 文章内容

高级类型

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-19 4:45:29

由 Shaodengdeng 创建, 最后一次修改 2016-08-12 高级类型视界(“类型类”)有时候,你并不需要指定一个类型是等/子/超于另一个类,你可以通过转换这个类来伪装这种关联关系。一个视界指定一个类型可以被“看作是”另一个类型。这对对象的只读操作是很有用的。隐函数允许类型自动转换。更确切地说,在隐式函数可以帮助满足类型推断时,它们允许按需的函数应用。例如:scala> implicit def strToInt(x: String) = x.toIntstrToInt: (x: String)Intscala> "123"res0: java.lang.String = 123scala> val y: Int = "123"y: Int = 123scala> math.max("123", 111)res1: Int = 123视界,就像类型边界,要求对给定的类型存在这样一个函数。您可以使用<%指定类型限制,例如:scala> class Container[A <% Int] { def addIt(x: A) = 123 + x }defined class Container这是说 A 必须“可被视”为 Int 。让我们试试。scala> (new Container[String]).addIt("123")res11: Int = 246scala> (new Container[Int]).addIt(123) res12: Int = 246scala> (new Container[Float]).addIt(123.2F)<console>:8: error: could not find implicit value for evidence parameter of type (Float) => Int (new Container[Float]).addIt(123.2) ^其他类型限制方法可以通过隐含参数执行更复杂的类型限制。例如,List 支持对数字内容执行 sum,但对其他内容却不行。可是 Scala 的数字类型并不都共享一个超类,所以我们不能使用T <: Number。相反,要使之能工作,Scala 的 math 库对适当的类型 T 定义了一个隐含的 Numeric[T]。 然后在 List 定义中使用它:sum[B >: A](implicit num: Numeric[B]): B如果你调用List(1,2).sum(),你并不需要传入一个 num 参数;它是隐式设置的。但如果你调用 List("whoop").sum(),它会抱怨无法设置 num。在没有设定陌生的对象为 Numeric 的时候,方法可能会要求某种特定类型的“证据”。这时可以使用以下类型-关系运算符:A =:= B A 必须和 B 相等A <:< B A 必须是 B 的子类A <%< B A 必须可以被看做是 Bscala> class Container[A](value: A) { def addIt(implicit evidence: A =:= Int) = 123 + value }defined class Containerscala> (new Container(123)).addItres11: Int = 246scala> (new Container("123")).addIt<console>:10: error: could not find implicit value for parameter evidence: =:=[java.lang.String,Int]类似地,根据之前的隐式转换,我们可以放松约束为可视性:scala> class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value }defined class Containerscala> (new Container("123")).addItres15: Int = 246使用视图进行泛型编程在 Scala 标准库中,视图主要用于实现集合的通用函数。例如“min”函数(在 Seq[] 上)就使用了这种技术:def min[B >: A](implicit cmp: Ordering[B]): A = { if (isEmpty) throw new UnsupportedOperationException("empty.min") reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)}其主要优点是:集合中的元素并不是必须实现 Ordered 特质,但 Ordered 的使用仍然可以执行静态类型检查。无需任何额外的库支持,你也可以定义自己的排序:scala> List(1,2,3,4).minres0: Int = 1scala> List(1,2,3,4).min(new Ordering[Int] { def compare(a: Int, b: Int) = b compare a })res3: Int = 4作为旁注,标准库中有视图来将 Ordered 转换为 Ordering (反之亦然)。trait LowPriorityOrderingImplicits { implicit def ordered[A <: Ordered[A]]: Ordering[A] = new Ordering[A] { def compare(x: A, y: A) = x.compare(y) }}上下文边界和implicitly[]Scala2.8 引入了一种串联和访问隐式参数的快捷方式。scala> def foo[A](implicit x: Ordered[A]) {}foo: [A](implicit x: Ordered[A])Unitscala> def foo[A : Ordered] {} foo: [A](implicit evidence$1: Ordered[A])Unit隐式值可能会通过 implicitly 被访问scala> implicitly[Ordering[Int]]res37: Ordering[Int] = scala.math.Ordering$Int$@3a9291cf相结合后往往会使用更少的代码,尤其是串联视图的时候。更高级多态性类型和特设多态性Scala 可以对“更高阶”的类型进行抽象。例如,假设您需要用几种类型的容器处理几种类型的数据。你可能定义了一个 Container 的接口,它可以被实现为几种类型的容器:Option、List 等。你要定义可以使用这些容器里的值的接口,但不想确定值的类型。这类似与函数柯里化。例如,尽管“一元类型”有类似List[A]的构造函数,这意味着我们必须满足一个“级别”的类型变量来产生一个具体的类型(就像一个没有柯里化的函数需要只提供一个参数列表来被调用),更高阶的类型需要更多。scala> trait Container[M[_]] { def put[A](x: A): M[A]; def get[A](m: M[A]): A }scala> val container = new Container[List] { def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head }container: java.lang.Object with Container[List] = $anon$1@7c8e3f75scala> container.put("hey")res24: List[java.lang.String] = List(hey)scala> container.put(123)res25: List[Int] = List(123)注意:Container是参数化类型的多态(“容器类型”)。如果我们结合隐式转换 implicits 使用容器,我们会得到“特设的”多态性:即对容器写泛型函数的能力。scala> trait Container[M[_]] { def put[A](x: A): M[A]; def get[A](m: M[A]): A }scala> implicit val listContainer = new Container[List] { def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head }scala> implicit val optionContainer = new Container[Some] { def put[A](x: A) = Some(x); def get[A](m: Some[A]) = m.get }scala> def tupleize[M[_]: Container, A, B](fst: M[A], snd: M[B]) = { | val c = implicitly[Container[M]] | c.put(c.get(fst), c.get(snd)) | }tupleize: [M[_],A,B](fst: M[A],snd: M[B])(implicit evidence$1: Container[M])M[(A, B)]scala> tuplei

[1] [2]  下一页


高级类型