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

高级类型

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

ze(Some(1), Some(2))res33: Some[(Int, Int)] = Some((1,2))scala> tupleize(List(1), List(2))res34: List[(Int, Int)] = List((1,2))F-界多态性通常有必要来访问一个(泛型)特质的具体子类。例如,想象你有一些泛型特质,但需要可以与它的某一子类进行比较。trait Container extends Ordered[Container]然而,现在比较方法是必须的了def compare(that: Container): Int因此,我们不能访问具体子类型,例如:class MyContainer extends Container { def compare(that: MyContainer): Int}编译失败,因为我们对 Container 指定了 Ordered 特质,而不是对特定子类型指定的。为了调和这一点,我们改用F-界的多态性。trait Container[A <: Container[A]] extends Ordered[A]奇怪的类型!但可以看到怎样对 A 实现了 Ordered 参数化,它本身就是 Container[A]所以,现在class MyContainer extends Container[MyContainer] { def compare(that: MyContainer) = 0 }他们是有序的了:scala> List(new MyContainer, new MyContainer, new MyContainer)res3: List[MyContainer] = List(MyContainer@30f02a6d, MyContainer@67717334, MyContainer@49428ffa)scala> List(new MyContainer, new MyContainer, new MyContainer).minres4: MyContainer = MyContainer@33dfeb30鉴于他们都是 Container[_] 的子类型,我们可以定义另一个子类并创建 Container[_] 的一个混合列表:scala> class YourContainer extends Container[YourContainer] { def compare(that: YourContainer) = 0 }defined class YourContainerscala> List(new MyContainer, new MyContainer, new MyContainer, new YourContainer) res2: List[Container[_ >: YourContainer with MyContainer <: Container[_ >: YourContainer with MyContainer <: ScalaObject]]] = List(MyContainer@3be5d207, MyContainer@6d3fe849, MyContainer@7eab48a7, YourContainer@1f2f0ce9)注意结果类型是怎样成为 YourContainer 和 MyContainer 类型确定的下界。这是类型推断的工作。有趣的是,这种类型甚至不需要是有意义的,它只是提供了一个合乎逻辑的最大下界为列表的统一类型。如果现在我们尝试使用 Ordered 会发生什么?(new MyContainer, new MyContainer, new MyContainer, new YourContainer).min<console>:9: error: could not find implicit value for parameter cmp: Ordering[Container[_ >: YourContainer with MyContainer <: Container[_ >: YourContainer with MyContainer <: ScalaObject]]]对统一的类型 Ordered[] 不存在了。结构类型Scala 支持结构类型 structural types — 类型需求由接口构造表示,而不是由具体的类型表示。scala> def foo(x: { def get: Int }) = 123 + x.getfoo: (x: AnyRef{def get: Int})Intscala> foo(new { def get = 10 }) res0: Int = 133这可能在很多场景都是相当不错的,但这个实现中使用了反射,所以要注意性能!抽象类型成员在特质中,你可以让类型成员保持抽象。scala> trait Foo { type A; val x: A; def getX: A = x }defined trait Fooscala> (new Foo { type A = Int; val x = 123 }).getX res3: Int = 123scala> (new Foo { type A = String; val x = "hey" }).getXres4: java.lang.String = hey在做依赖注入等情况下,这往往是一个有用的技巧。您可以使用 hash 操作符来引用一个抽象类型的变量:scala> trait Foo[M[_]] { type t[A] = M[A] }defined trait Fooscala> val x: Foo[List]#t[Int] = List(1)x: List[Int] = List(1)类型擦除和清单正如我们所知道的,类型信息在编译的时候会因为擦除而丢失。 Scala 的清单(Manifests)功能,使我们能够选择性地恢复类型信息。清单提供了一个隐含值,根据需要由编译器生成。scala> class MakeFoo[A](implicit manifest: Manifest[A]) { def make: A = manifest.erasure.newInstance.asInstanceOf[A] }scala> (new MakeFoo[String]).makeres10: String = ""案例分析: Finagle参见: https://github.com/twitter/finagletrait Service[-Req, +Rep] extends (Req => Future[Rep])trait Filter[-ReqIn, +RepOut, +ReqOut, -RepIn] extends ((ReqIn, Service[ReqOut, RepIn]) => Future[RepOut]){ def andThen[Req2, Rep2](next: Filter[ReqOut, RepIn, Req2, Rep2]) = new Filter[ReqIn, RepOut, Req2, Rep2] { def apply(request: ReqIn, service: Service[Req2, Rep2]) = { Filter.this.apply(request, new Service[ReqOut, RepIn] { def apply(request: ReqOut): Future[RepIn] = next(request, service) override def release() = service.release() override def isAvailable = service.isAvailable }) } } def andThen(service: Service[ReqOut, RepIn]) = new Service[ReqIn, RepOut] { private[this] val refcounted = new RefcountedService(service) def apply(request: ReqIn) = Filter.this.apply(request, refcounted) override def release() = refcounted.release() override def isAvailable = refcounted.isAvailable } }一个服务可以通过过滤器对请求进行身份验证。trait RequestWithCredentials extends Request { def credentials: Credentials}class CredentialsFilter(credentialsParser: CredentialsParser) extends Filter[Request, Response, RequestWithCredentials, Response]{ def apply(request: Request, service: Service[RequestWithCredentials, Response]): Future[Response] = { val requestWithCredentials = new RequestWrapper with RequestWithCredentials { val underlying = request val credentials = credentialsParser(request) getOrElse NullCredentials } service(requestWithCredentials) }}注意底层服务是如何需要对请求进行身份验证的,而且还是静态验证。因此,过滤器可以被看作是服务转换器。许多过滤器可以被组合在一起:val upFilter = logTransaction andThen handleExceptions andThen extractCredentials andThen homeUser andThen authenticate andThen route享用安全的类型吧!

上一页  [1] [2] 


高级类型