如何在Scala中使用类型参数声明匿名mixin



有人问了一些与这个问题有些相关的问题,但这些问题似乎不太合适。

我使用Cake模式将"存储"系统滑入生产代码中,并将存根存储系统滑入以进行测试。这一切都很好,但有一个类正在原始类中实例化,它也需要混合这个存根存储系统。由于它隐藏在实现中,我无法访问它。

事情看起来是这样的:

class Main { this: Storage =>
  ...
  val used = Used(...)
  ...
}
class Used { this: Storage =>
  ...
}

当测试"已用"时,我只需new Used with StubStorage,然后关闭。我曾经对Main做过同样的事情,但那是在它使用Used之前。既然MainUsed进行了简单的实例化,我就遇到了这个问题。

我想这样试试:

class Main[T <: Storage] { this: T =>
  ...
  val used = Used[T](...)
  ...
}
class Used[T <: Storage] { this: T =>
  ...
}
object Used {
  def apply[T <: Storage](...) = new Used(...) with T
}

但这当然不起作用,因为编译器没有足够的信息来发现T。有什么神奇的配方吗?我已经玩了一段时间,它看起来很麻烦,标准OO注入方法实际上没有那么麻烦,但我可能会错过一些东西。

我已经研究过隐含的工厂概念,但我无法将其转化为用于混合的形状。

编辑:公开撰写问题的清晰度令人惊讶。:)我还没有按照我最初打算的方式解决这个问题,但有一个简单的解决实际问题的方法:

trait UsedProvider {
  def createUsed = Used.apply _
}
class Main { this: Storage with UsedProvider =>
  val used = createUsed(...)
}

那么我只需要在测试中做以下操作:new Main with StubStorage with StubUsedProvider

我也没有解决您最初的问题,但您是否考虑过为Main使用抽象类,并在需要的地方为used提供值?

abstract class Main { this: Storage =>
  val s = "s"
  val used: Used
}

然后像这样实例化:

val main = new Main with StubStorage { val used = new Used(s) with StubStorage }

最新更新