我以为这已经被问到了,但是,如果是这样的话,这个问题在“相关”栏中并不明显。这就是:
什么是视图边界?
A.
Scala中引入了一种机制来支持某种类型的
A
犹如
那是某种类型的
B
。典型的语法如下:
def f[A <% B](a: A) = a.bMethod
换句话说,,
A.
B
可供选择,以便拨打电话
。在标准库中(无论如何,在Scala 2.8.0之前),视图边界最常见的用法是
Ordered
,例如:
def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b
因为一个人可以转化
Ordered[A]
,因为
命令的[A]
<(other: A): Boolean
a < b
view bounds are deprecated
,你应该避开它们。
什么是上下文约束?
上下文边界是在Scala2.8.0中引入的,通常用于所谓的
,这是一种代码模式,它模拟Haskell类型类提供的功能,但方式更为详细。
A <% String
在上面,但不同于
String
.
上下文绑定描述隐式
价值
转变
。它用于声明某些类型的
,存在类型为的隐式值
B[A]
可获得的语法如下所示:
def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]
def f[A : ClassManifest](n: Int) = new Array[A](n)
Array
参数化类型上的初始化需要
ClassManifest
由于与类型擦除和数组的非擦除性质相关的神秘原因,该文件将可用。
库中另一个非常常见的示例稍微复杂一些:
def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
在这里
implicitly
用于检索所需的隐式值,类型为
Ordering[A]
,哪个类定义了该方法
compare(a: A, b: A): Int
我们将在下面看到另一种方法。
def f[A <% B](a: A) = a.bMethod
def f[A](a: A)(implicit ev: A => B) = a.bMethod
def g[A : B](a: A) = h(a)
def g[A](a: A)(implicit ev: B[A]) = h(a)
因此,很自然,我们可以用完整的语法编写它们,这对于上下文边界特别有用:
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)
视图边界主要用于利用
皮条客我的图书馆
模式,在希望以某种方式返回原始类型的情况下,通过该模式向现有类“添加”方法。如果不需要以任何方式返回该类型,则不需要视图绑定。
.注意
Int
不是
命令
,例如,尽管存在隐式转换。前面给出的示例需要视图绑定,因为它返回未转换的类型:
def f[A <% Ordered[A]](a: A, b: A): A = if (a < b) a else b
如果没有视图边界,此示例将无法工作。但是,如果要返回另一个类型,则不再需要视图绑定:
def f[A](a: Ordered[A], b: A): Boolean = a < b
这里的转换(如果需要)发生在我将参数传递给
f
所以
F
此外
命令
一串
和
,它们是Java类,就像Scala集合一样。例如:
def f[CC <% Traversable[_]](a: CC, b: CC): CC = if (a.size < b.size) a else b
一串
将是一个
WrappedString
大堆
.
即使该类型仅用作返回类型的类型参数,也会发生同样的情况:
def f[A <% Ordered[A]](xs: A*): Seq[A] = xs.toSeq.sorted
上下文边界用于什么?
类型类模式
,作为对Haskell类型类的引用。基本上,此模式通过一种隐式适配器模式使功能可用,从而实现继承的替代方案。
典型的例子是Scala 2.8
Ordering
整个Scala的图书馆。用法是:
def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = {
import ord.mkOrderingOps
if (a < b) a else b
}
它利用了内部的一些隐式转换
这将启用传统的运算符样式。Scala 2.8中的另一个示例是
Numeric
def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)
一个更复杂的例子是新的集合用法
CanBuildFrom
,但是已经有一个很长的答案,所以我在这里避免。如前所述,还有
类清单
与typeclass模式绑定的上下文更有可能被您自己的类使用,因为它们支持关注点的分离,而视图边界可以通过良好的设计在您自己的代码中避免(它主要用于绕过其他人的设计)。
虽然上下文边界的使用已经有很长一段时间了,但它在2010年已经真正开始使用,并且在某种程度上在大多数Scala最重要的库和框架中都可以找到。不过,它使用的最极端的例子是Scalaz库,它为Scala带来了Haskell的强大功能。我建议阅读typeclass模式,以便更好地了解它的所有使用方法。
编辑