如何在Scala中组织公共代码

时间:2013-07-24 20:44:35

标签: scala scala-2.10

我有一个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方法?将孩子类型传递给父母特质对我来说似乎有点蠢。这样可以吗?

2 个答案:

答案 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 ...

之类的内容