我有一个Scala程序,它有几个包含许多常用代码的类。很多代码都是通用的,所以你有这样的东西(使用TypeTags来保存类型信息):
object ModelA {
def update(id: UUID, changes: Map[String, Any]) = {
Validate.partialInstanceOf[ModelA](changes) match {
...
}
}
}
和......
object ModelB {
def update(id: UUID, changes: Map[String, Any]) = {
Validate.partialInstanceOf[ModelB](changes) match {
...
}
}
}
我对Scala相当新,所以我想知道干燥这段代码的最佳方法是什么。我看到两种可能性:特质或辅助类。这就是我对这个特性的想法:
trait Model[M <: Model] {
def update(id: UUID, changes: Map[String, Any]) = {
Validate.partialInstanceOf[M](changes) match {
...
}
}
}
object ModelA extends Model[ModelA]
object ModelB extends Model[ModelB]
...这就是我对助手类的想法:
object ModelHelper {
def update[M](id: UUID, changes: Map[String, Any]) = {
Validate.partialInstanceOf[M](changes) match {
...
}
}
}
object ModelA {
def update(id: UUID, changes: Map[String, Any]) = {
ModelHelper.update[ModelA](id, changes);
}
}
...
我的问题是:什么是更惯用的Scala方法?将孩子类型传递给父母特质对我来说似乎有点蠢。这样可以吗?
答案 0 :(得分:3)
使用这种特性更为惯用,因为它是DRYer。 Scala库可以在任何地方完成它,例如:
object ArrayBuffer extends SeqFactory[ArrayBuffer] ...
答案 1 :(得分:2)
如果您可能想要混合提供功能的不同方面的多个特征,所有这些都需要知道他们使用的特定类型,您可能需要考虑以下模式:
trait Updatable {
type M
def update(id: UUID, changes: Map[String, Any]) = {
Validate.partialInstanceOf[M](changes) match {
...
}
}
}
trait Jsonable {
type M
def toJson(model: M) = {
...
}
}
... other functionality traits ...
object ModelA extends Updatable with Jsonable with ... { type M = ModelA.type }
object ModelB extends Updatable with Jsonable with ... { type M = ModelB.type }
class ModelC extends Updatable with Jsonable with ... { type M = ModelC } // Example for class types rather than objects, if that is relevant.
然后,您可以独立测试每个特征的功能,而不必开始编写object ModelD extends Updatable[ModelD] with Jsonable[ModelD] with ...