Tim*_*ske 5 scala abstract-type
给出的方法下面的代码foo要比运营商明智的给定参数bar与lowerBound和upperBound相同的抽象类型全部为Bar.
trait Foo {
type Bar <: Ordered[Bar]
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar) = bar >= lowerBound && bar <= upperBound
}
Run Code Online (Sandbox Code Playgroud)
这样Foo就可以定义特征.问题从下面的具体类开始FooImpl.
class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
Run Code Online (Sandbox Code Playgroud)
据我所知,scala.Int这scala.runtime.RichInt并没有有效地实现scala.math.Ordered[Int].将类型定义Bar为RichInt不起作用,因为它不符合scala.math.Ordered[RichInt].我第三次尝试将类型定义为声明Bar为Ordered[Ord]where 并将其定义为也不起作用.Ordtype OrdFooImplInt
一个可能接近的解决方案怎么样?
可能有一个更优雅的解决方案,但您可以通过将类型的限制移动到方法而不是类型声明来实现此目的:
trait Foo {
type Bar
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar)(implicit ev: Bar => Ordered[Bar]) = {
bar >= lowerBound && bar <= upperBound
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的FooImpl工作就像你拥有它:
class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
Run Code Online (Sandbox Code Playgroud)
来自REPL:
scala> new FooImpl()
res0: FooImpl = FooImpl@2dbbec72
scala> res0.foo(3)
res1: Boolean = true
scala> res0.foo(7)
res2: Boolean = false
Run Code Online (Sandbox Code Playgroud)
这里的缺点是特征可以用无序类型扩展(尽管foo在这种情况下不能调用):
class A // not Ordered
class BrokenFoo extends Foo {
type Bar = A
val lowerBound = new A
val upperBound = new A
} // compiles
new BrokenFoo().foo(new A) // doesn't compile
Run Code Online (Sandbox Code Playgroud)
或者,您可以将需求保持在类级别(因此阻止任何人创建BrokenFoo),如下所示,但FooImpl必须稍微更改:
trait Foo {
type Bar
implicit val baz: Bar => Ordered[Bar]
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar) = { bar >= lowerBound && bar <= upperBound }
}
class FooImpl extends Foo {
type Bar = Int
val baz = implicitly[Bar => Ordered[Bar]]
val lowerBound = 0
val upperBound = 5
}
Run Code Online (Sandbox Code Playgroud)
这个问题感觉像视图或上下文边界应该适用,但不幸的是,你似乎不能在type声明或特征上的泛型类型参数中使用它们.
| 归档时间: |
|
| 查看次数: |
575 次 |
| 最近记录: |