2012-02-13 70 views
4

给出的方法foo下面的代码应该比较操作者明智给定参数barlowerBoundupperBound所有是相同的抽象类型Bar的。如何比较Scala特征中的有序抽象类型?

trait Foo { 
    type Bar <: Ordered[Bar] 
    val lowerBound: Bar 
    val upperBound: Bar 
    def foo(bar: Bar) = bar >= lowerBound && bar <= upperBound 
} 

这样可以定义特征Foo。问题始于下面的具体类FooImpl

class FooImpl extends Foo { 
    type Bar = Int 
    val lowerBound = 0 
    val upperBound = 5 
} 

我明白scala.Int不执行什么scala.runtime.RichInt确实,有效scala.math.Ordered[Int]。将类型Bar定义为RichInt而不适用,因为它不符合scala.math.Ordered[RichInt]。我的第三次尝试将Bar类型定义为​​,其中Ord被宣布为type Ord并将其定义为FooImpl,因为Int也不起作用。

一个可能接近的解决方案将如何看起来像?

回答

7

有可能是一个更好的解决方案,但你可以通过在类型移动限制的方法,而不是类型声明实现这一点:

trait Foo { 
    type Bar 
    val lowerBound: Bar 
    val upperBound: Bar 
    def foo(bar: Bar)(implicit ev: Bar => Ordered[Bar]) = { 
    bar >= lowerBound && bar <= upperBound 
    } 
} 

然后你FooImpl的作品,你就会明白:

class FooImpl extends Foo { 
    type Bar = Int 
    val lowerBound = 0 
    val upperBound = 5 
} 

从REPL:

scala> new FooImpl() 
res0: FooImpl = [email protected] 

scala> res0.foo(3) 
res1: Boolean = true 

scala> res0.foo(7) 
res2: Boolean = false 

的d这里isadvantage是性状可以用无序类型的扩展(尽管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 

或者,您可以在类级别保持需求(并因此阻止任何人创建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 
} 

这个问题感觉就像view or context bounds应该是适用的,但不幸的是它似乎并不像你既可以在type声明或在泛型类型参数使用它们性状。

+2

是的,如果OP愿意把Foo变成一个抽象类,那么'Bar'类型的成员可以废除,Foo的第一行的声明可以作为“抽象类Foo [Bar <%Ordered [酒吧]]”。这可能会比在一种方法上强制执行这种关系更好。 – Destin 2012-02-13 01:45:01