抽象类型与类型参数 [英] Abstract types versus type parameters

查看:46
本文介绍了抽象类型与类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在什么情况下抽象类型应该优先于类型参数?

In what situations should abstract types be preferred over type parameters?

推荐答案

添加到我的先前关于抽象类型与参数的答案,您还有 JESSE EICHAR 最近的博文(2010 年,5 月 3 日)强调了一些主要差异:

To add to my previous answer on Abstract type vs. parameters, you have also the JESSE EICHAR's recent blog post (2010, May 3rd) highlighting some key differences:

trait C1[A] {
  def get : A
  def doit(a:A):A
}
trait C2 {
  type A
  def get : A
  def doit(a:A):A
}

C2的情况下,参数被埋没"(作为内部抽象类型).
(除了,正如retronym所说,它实际上并没有被埋葬,见下文)

In C2 case, the parameter is "buried" (as an internal abstract type).
(except, as retronym puts it, it is not actually buried, see below)

而对于泛型类型,参数被明确提及,帮助其他表达式知道它们应该使用什么类型

Whereas with generic type, the parameter is explicitly mentioned, helping other expressions to know what type they are supposed to used

所以(C1:参数):

//compiles
def p(c:C1[Int]) = c.doit(c.get)

它可以编译,但您显式公开了您要使用的A"类型.

It compiles, but you expose explicitly the 'A' type you want to use.

And(C2:抽象类型):

And (C2: Abstract type):

// doesn't compile
def p2(c:C2) = c.doit(c.get)
<console>:6: error: illegal dependent method type
       def p2(c:C2) = c.doit(c.get)
              ^

它不会编译,因为在 p2 定义中从未提到 'A',所以 doit 在编译类型时不知道它应该返回什么.

It doesn't compile because 'A' is never mentioned in p2 definition, so doit doesn't know at compile type what it is supposed to return.

当使用抽象类型并且想要避免任何类型泄漏"到接口时(即想要公开A"实际上是什么),您可以指定一个非常通用的类型作为 p2 的返回:

When using abstract type and wanting to avoid any "type leaking" to the interface (i.e. wanting to expose what 'A' actually is), you could specify a very generic type as a return for p2:

// compiles because the internals of C2 does not leak out
def p(c:C2):Unit = c.doit(c.get)

或者您可以直接在 doit 函数中修复"该类型:
def doit(a:A):Int 而不是 def doit(a:A):A,意思是:
def p2(c:C2) = c.doit(c.get) 会编译(即使 p2 没有提到任何返回类型)

Or you could "fix" that type directly in the doit function:
def doit(a:A):Int instead of def doit(a:A):A, which means:
def p2(c:C2) = c.doit(c.get) will compile (even if p2 doesn't mention any return type)

最后(retronym 的评论)您可以通过改进 C2 显式指定 A抽象参数:

Finally (retronym's comment) you can specify A either explicitly by refining C2 abstract parameter:

scala> def p2(c:C2 { type A = Int }): Int = c.doit(c.get)
p2: (c: C2{type A = Int})Int

或者通过添加类型参数(并用它改进 C2 抽象类型!)

Or by adding a type parameter (and refining C2 abstract type with it!)

scala> def p2[X](c:C2 { type A = X }): X = c.doit(c.get)
p2: [X](c: C2{type A = X})X

<小时>

推荐这么抽象:


So abstract are recommended:

  • 当您想从客户端代码中隐藏类型成员的确切定义时,请使用 C2 中的抽象类型(但要注意使用C2)
  • 当你想在 C2 的子类中协变覆盖类型时,使用抽象类型(有界类型抽象)
  • 当你想通过特性混合那些C2类型的定义时,使用抽象类型(你不会有'A'将 C2 与您的类混合时要处理的问题:您只混合 C2)
  • When you want to hide a the exact definition of a type member from client code, use abstract type like in C2 (but be wary of the definition of function using C2)
  • When you want to override the type covariantly in subclasses of C2, use abstract type (with bounded type abstraction)
  • When you want to mix in definitions of those C2 types via traits, use abstract type (you won't have 'A' to deal with when mixing C2 with your class: you mix only C2)

其余的,如果需要简单的类型实例化,请使用参数.
(如果你知道不需要扩展,但你仍然需要处理几种类型:这就是参数类型的用途)

For the rest, where simple type instantiation is need, use Parameters.
(if you know that no extension will be needed, but you still have to handle several types: that is what Parameter types are for)

retronym 补充:

主要区别

  • variance:C2只能在A中保持不变,
  • 在子类型中选择性覆盖类型成员的方式(而类型参数必须重新声明并传递给超类型)
  • variance: C2 can only be invariant in A,
  • the way that type members can be selectively overriden in a subtype (whereas type parameters must be redeclared and passed to the supertype)

(如在此处说明:

trait T1 {
  type t
  val v: t
}
trait T2 extends T1 {
  type t <: SomeType1
}
trait T3 extends T2 {
  type t <: SomeType2  // where SomeType2 <: SomeType1
}
class C extends T3 {
  type t = Concrete    // where Concrete <: SomeType2
  val v = new Concrete(...)
}

)

这篇关于抽象类型与类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆