隐式类

时间:2016-12-22 16:00:57

标签: scala

我正在使用一个类(我无法修改),其中包含一个接收Any类型值作为参数的方法,如下例所示:

class Foo(value: Int) {
  def +(other: Any): Foo = ???
}

我希望在方法+()与特定类型一起使用时添加自定义实现。我希望能够做到这样的事情:

implicit class RichFoo(foo: Foo) {
  def +(other: Int): Foo = ???
}

// or

implicit class RichFoo(foo: Foo) {
  def +[T <: Bar](other: T): T = ???
}

但是,这些方法不起作用。

是否可以不延长原班级?

2 个答案:

答案 0 :(得分:3)

没有

对于编译器,隐式转换和其他重写规则(如.desktop { display: flex; align-items: center; } .root-nav-links { margin: 0 15px; padding: 2px 6px; } 周围的那些)是各种各样的“最后手段”。它们仅在代码尚未按原样检查时应用。执行Dynamic时,编译器已经知道foo + x需要+,因此它甚至不会尝试查找隐含。如果您执行了Any,并且foo - x没有正确类型的Foo,那么编译器只会搜索转换。

相反,您可以使用-中不存在但add中存在的新名称(可能为Foo)创建方法。但是,这不会阻止您执行RichFoo而不是foo + 1,因为这两种方法都有效。

foo add 1

答案 1 :(得分:2)

您可以使用幻像类型来跟踪可转换的内容。

SetItemVisibilityByPattern(resultField, "(4K[24A]|685|923).*")

给定的东西:

scala> trait Tagged[B]
defined trait Tagged

scala> type Of[+A, B] = A with Tagged[B]
defined type alias Of

scala> class Tagger[B] { def apply[A](a: A): A Of B = a.asInstanceOf[A Of B] }
defined class Tagger

scala> object tag { def apply[B]: Tagger[B] = new Tagger[B] }
defined object tag

和标记特征:

scala> case class C(i: Int) { def +(x: Any): C = C(i + x.toString.toInt) }
defined class C

通常:

scala> trait CC
defined trait CC

这有效:

scala> C(42) + "17"
res0: C = C(59)

但不是这样:

scala> val cc = tag[CC](C(42))
cc: Of[C,CC] = C(42)

也许这个:

scala> val cc = tag[CC](C(42): Any)
java.lang.ClassCastException: C cannot be cast to Tagged
  ... 29 elided

然后:

scala> val cc = tag[CC](C(42): Serializable)
cc: Of[Serializable,CC] = C(42)

异常:

scala> implicit class XC(v: Serializable Of CC) {
     | def +(x: Any): C Of CC = tag[CC] {
     |   println("OK")
     |   v.asInstanceOf[C] + x
     | }}
defined class XC

肯定有更好的方法可以做到这一点:

scala> val valueAdded = cc + "17"
OK
valueAdded: Of[C,CC] = C(59)

因为它毁了它:

scala> implicit def untagit(x: Serializable Of CC): C Of CC = tag[CC](x.asInstanceOf[C]) 
untagit: (x: Of[Serializable,CC])Of[C,CC]

scala> cc.i
res9: Int = 42