【发布时间】:2021-01-10 05:07:30
【问题描述】:
我浏览了documentation 并找到了几种方法来定义类型类实例的临时行为。这是原始示例:
trait Ord[T] {
def compare(x: T, y: T): Int
extension (x: T) def < (y: T) = compare(x, y) < 0
extension (x: T) def > (y: T) = compare(x, y) > 0
}
有趣的是我们可以定义一堆普通的中缀方法和扩展。用户期望的行为应该是相同的(尽管实现不同)。
trait RankEq[T]:
extension (x: T)
def equal (y: T): Boolean
extension (x: T)
def notEqual (y: T): Boolean = !rankEqual(y)
trait RankOrd[T] {
def rankCompare(x: T, y: T): Int
def (x: T) isLower (y: T): Boolean =
rankCompare(x, y) == -1
def (x: T) isHigher (y: T): Boolean =
rankCompare(x, y) == 1
}
下面的例子说明了这一点:
given rankEq as RankEq[Rank] {
extension (x: Rank)
def equal (y: Rank) = (x.ordinal - y.ordinal) == 0
}
given rankOrd as RankOrd[Rank] {
override def rankCompare(x: Rank, y: Rank): Int = {
x.ordinal - y.ordinal
}
}
object Rank {
def beats(r1: Rank, r2: Rank)
(using RankEq[Rank])(using RankOrd[Rank]): Boolean = {
if r1.equal(r2) then false // extension methods
else r1.isHigher(r2) // trait-member infix method
}
}
由于两种构造都在做同样的事情(以不同的方式),这就提出了一个问题:哪种方式最惯用?如果两者都适用,在哪种情况下效果最好?
谢谢!
【问题讨论】:
-
你没有提供
Rank的定义。 -
关于一个有扩展方法的类型类和一个有普通方法+通过普通方法表达的扩展方法的类型类,这只是Scala中的另一件事,可以通过多种不同的方式来完成。
-
@DmytroMitin 我省略了Rank定义是因为它应该是一个普通的枚举
-
扩展方法语法一直在变化,甚至相对recently。
标签: scala extension-methods typeclass dotty scala-3