我有一个抽象类(这是一个类似的例子) Printer,它打印提供的参数,除非它不能传递一个过滤器。Printer是逆变异的w.r.t.其泛型类型为T。
class Printer[-T] {
val filters: Seq[Function2[T => Boolean]]
def print(t: T): Unit {
if (filters.forall(_(t))) doPrint(t)
}
def doPrint(t: T): Unit
}我现在有20个Printer的子类--一个用于String、Ints等。因为Printer是反变体,所以filters必须是一个val。但是,如果我想要一个Printer方法添加一个过滤器,它需要是不可变的。
def addFilter[TT <: T](t: TT): Printer[TT]不幸的是,我现在需要在我的20个子类中实现这个方法。有办法绕过这件事吗?
更新:另外,在addFilter中,我不知道如何返回子类而不是超类Printer。例如,如果我在一个addFilter上调用StringPrinter,那么理想情况下,我会得到StringPrinter类型。
发布于 2013-10-17 03:24:30
THe下面的代码与您编写Printer的方式有点不同,但可能会实现您的意图。请注意,这种编写类代码的方式可以更好地分离关注点:您可以定义过滤器和打印实现( doPrint参数),而不管它们是如何使用的:
case class Printer[T](val filters: List[Function1[T, Boolean]], val doPrint: T => Unit) {
def print(t: T): Unit = {
if (filters.forall(_(t))) doPrint(t)
}
def addFilter[TT <: T](f: TT => Boolean): Printer[TT] = copy(f :: filters)
}请注意,我不需要在这里指定对比,不确定这是否会成为您的问题。
要使用该类,不需要子类,只需将适当的参数传递到构造函数(实际上,为case类免费提供的配套apply工厂方法)-例如:
case class Foo(x: Int)
val fooChk1: Foo => Boolean = (f: Foo) => f.x != 1
val fooPrinter1 = Printer(fooChk1 :: Nil, (f: Foo) => println(s"Foo: x = ${f.x}"))
val fooChk3: Foo => Boolean = (f: Foo) => f.x != 3
val fooPrinter2 = fooPrinter1.addFilter(fooChk3)
val foo3 = Foo(3)
fooPrinter1.print(foo3) // Prints 'Foo: x = 3'
fooPrinter3.print(foo3) // Prints nothing在这里也有一个相当大的使用范围,这两个参数都适用于Print (例如。将构造函数更改为(val filters: List[Function1[T, Boolean]])(implicit val doPrint: T => Unit)),并针对特定的Print[X]变体。
https://stackoverflow.com/questions/19416634
复制相似问题