Scala Pimp my library模式应用于类层次结构
我有下面的类层次结构Scala Pimp my library模式应用于类层次结构,scala,polymorphism,implicit,Scala,Polymorphism,Implicit,我有下面的类层次结构 sealed abstract class A case class B extends A case class C extends A 现在,我想在类a、B和C中添加foo方法。但我不想以任何方式改变课程。因此,我应用pimp my library模式如下 abstract class RichA(a: A) { def foo } class RichB(b: B) extends RichA(b){ def foo = { println("B")
sealed abstract class A
case class B extends A
case class C extends A
现在,我想在类a
、B
和C
中添加foo
方法。但我不想以任何方式改变课程。因此,我应用pimp my library模式如下
abstract class RichA(a: A) {
def foo
}
class RichB(b: B) extends RichA(b){
def foo = { println("B"); //do something with b}
}
class RichC(c: C) extends RichA(c) {
def foo = { println("C"); //do something with c}
}
/////////////
implicit def A2RichA(a: A) = {
a match {
case a: B => new RichB(a)
case a: C => new RichC(a)
}
}
implicit def B2RichB(b: B) = new RichB(b)
implicit def C2RichC(c: C) = new RichC(c)
/////////////
def test() = {
def printA(a: A) = {
a.foo
}
val obj = new C
printA(obj)
}
test() //This prints "C"
这是可行的,但是
A2RichA
隐式函数的实现在我看来有点难看,因为它涉及到A的每个子类的case语句。这能以更优雅的方式完成吗?基本要求是,如果我对类型为a
的对象调用foo
,它应该在B
或C
中调用适当的方法foo
,具体取决于对象的动态类型。第一种方法:--根据操作要求不足--
假设foo
的单个实现适合您层次结构中的所有类,那么就可以了:
sealed abstract class A
case class B() extends A
case class C() extends A
class RichA(a: A) {
def foo() { println(this.a.getClass.getSimpleName) }
}
implicit def a2RichA(a: A): RichA = new RichA(a)
(new C).foo() /* anon$1$C */
第二种方法:——缺乏动态调度-- 我的第二种方法受到了该方法内部的启发。但是,它缺乏动态调度,因此仍然无法解决您的问题
sealed abstract class A
case class B() extends A
case class C() extends A
abstract class RichA(a: A) {
def foo(): Unit
}
class RichB(b: B) extends RichA(b) {
def foo() { println("Doing B-specific stuff") }
}
class RichC(c: C) extends RichA(c) {
def foo() { println("Doing C-specific stuff") }
}
sealed trait RichBuilder[T <: A] {
def apply(t: T): RichA
}
implicit object RichB extends RichBuilder[B] {
def apply(b: B) = new RichB(b)
}
implicit object RichC extends RichBuilder[C] {
def apply(c: C) = new RichC(c)
}
implicit def a2RichA[T <: A](t: T)
(implicit rb: RichBuilder[T])
: RichA = {
rb(t)
}
(new B).foo() /* B-specific */
(new C).foo() /* C-specific */
// (new C).asInstanceOf[A].foo() /* ERROR: Can't find an implicit */
密封抽象类A
case类B()扩展了
case类C()扩展了
抽象类RichA(a:a){
def foo():单位
}
类RichB(b:b)扩展了RichA(b){
def foo(){println(“做特定于B的事情”)}
}
类RichC(c:c)扩展了RichA(c){
def foo(){println(“做C特定的东西”)}
}
sealed trait RichBuilder[T通过允许编译器提供正确的转换,您可以使您的A2RichA
方法稍微优雅(或难以捉摸,取决于您的视角):
implicit def A2RichA(a: A): RichA =
a match {
case b: B => b // the compiler turns this into B2RichB(b)
case c: C => c // the compiler turns this into C2RichC(c)
}
implicit def B2RichB(b: B): RichA = new RichB(b)
implicit def C2RichC(c: C): RichA = new RichC(c)
但是,我不认为有更简单的方法可以解决这个基本问题:您希望提供基于参数的动态类型的转换。隐式搜索发生在编译时,因此只能提供基于静态类型的转换
您可以在运行时反射式地搜索转换,但这既不简单也不优雅(对于这样一个小的层次结构来说当然是不可取的)
由于您的层次结构是密封的,如果您在向层次结构中添加新类时忘记提供转换,编译器将向您发出警告。是否要将相同的foo
添加到您的类中,或者是否需要为a、B、C
中的每一个都使用不同的实现?抱歉,我将问题简化得太多。B
和C
可以有不同的数据,foo
的实现对于B
和C
是不同的。因为我的方法并不能真正解决问题-每个人,请反驳我的说法。谢谢你的指点..我需要一些时间来消化。
sealed abstract class A
case class B extends A
case class C extends A