鉴于这个简单的代码片段,我很惊讶地发现堆栈溢出很容易:
implicit def foobar: Unit = implicitly[Unit]
在我更复杂的用例中,我有以下情况:
abstract class Foo {
type Repr_Tpe
protected implicit def repr2Ordered: Repr_Tpe => Ordered[Repr_Tpe]
}
class Bar extends Foo {
type Repr_Tpe = Long
protected implicit def repr2Ordered = implicitly[Repr_Tpe => Ordered[Repr_Tpe]]
}
在类repr2Ordered
中定义方法Foo
不起作用,因为类型Repr_Tpe
是抽象的。所以我决定复制&粘贴声明并从中做出定义; 显然导致堆栈溢出。只有从类implicit
中的定义中删除修饰符Bar
才能解决此问题。
是不是有一个优雅的解决方案来规避这个陷阱?
答案 0 :(得分:0)
您已将foobar
定义为 类型Unit
的隐含值。然后,您已将定义为类型为Unit
的隐式值。用这种方式思考:
implicit def foobar: Unit = implicitly[Unit]
// you've defined foobar as the implicit value for Unit.
// so implicitly[Unit] is the same as calling foobar
// which is the same as:
implicit def foobar: Unit = foobar
你应该不会感到惊讶,这会导致堆栈溢出,而不是这个声明:
def tharSheBlows: Unit = tharSheBlows
对于更优雅的东西,我会使用view bound来确保类型参数为Ordered
。
scala> abstract class Foo[Repr_Tpe <% Ordered[Repr_Tpe]] {}
defined class Foo
scala> class Bar extends Foo[Long] {}
defined class Bar
scala> case class Unordered(data: String)
defined class Unordered
scala> class Bam extends Foo[Unordered] {}
<console>:10: error: No implicit view available from Unordered => Ordered[Unordered].
class Bam extends Foo[Unordered] {}
^
scala> implicit def bringOrder(u: Unordered) = new Ordered[Unordered] { def compare(that: Unordered) = u.data.compareTo(that.data) }
bringOrder: (u: Unordered)java.lang.Object with Ordered[Unordered]
scala> class Bam extends Foo[Unordered] {}
defined class Bam