接近分裂特征的正确方法

Correct way to approach splitting a trait

我有3个特质:

trait Worker

...

trait StringWorker extends Worker {
  def workString(): Iterator[String]
}

...

trait IntWorker extends Worker {
  def workInt(): Iterator[Int]
}

我的一些 类 仅扩展 StringWorker,而其他的则同时扩展 StringWorkerIntWorker

我的代码根据某些模式匹配获得正确的解析器,如下所示:

def getCorrectWorkerProvider: () => Worker = {
  case SomeCase => getStringWorkerProvider()
  case _ => getIntWorkerProvider()
}

如果我保持与上面写的相同的特征,那么我几乎总是不得不做这样的伪代码:

if working with string, then getCorrectWorkerProvider().asInstanceOf[StringWorker].workString

if working with int, then getCorrectWorkerProvider().asInstanceOf[IntWorker].workInt

而如果我将特征的定义更改为如下内容:

trait Worker {
  def workString(): Iterator[String]
  def workInt(): Iterator[Int]
}

trait StringWorker extends Worker
trait IntWorker extends Worker

那么我将永远不必使用 .asInstanceOf[SomeWorker] 来调用正确的方法。 我认为第一种方式更正确和直观,因为这些方法是特定于某个 Worker 的,但是第二种方式似乎不那么令人头疼。

我相信您正在寻找的是类型类模式。 Here's an article that explains the idea。基本上它的工作方式是创建一个函数,该函数接受类型 T 的值和隐式参数 Worker[T],然后 scala 的隐式解析机制为您找到正确的 Worker[T] .

这是一个例子:

object Main {
    def main(args: Array[String]): Unit = {
        work("String")
        work(3)
    }

    def work[T](value: T)(implicit worker: Worker[T]) = {
        worker.work(value)
    }
}


trait Worker[T]{
    def work(t: T): Iterator[T]
}

object Worker {
    implicit val stringWorker: Worker[String] = (t: String) => Iterator(t)
    implicit val intWorker: Worker[Int] = (t: Int) => Iterator(t)
}