如何在Scala中部分抽象方法

时间:2018-07-31 17:52:34

标签: scala abstract-class traits builder builder-pattern

此问题与this one有关。 我有一整套的Config类型的类,所有这些类都是使用构建器模式构建的。因此,我也有ConfigBuilder类,它们也形成一个层次结构,因为许多实现共享相同的行为。

我想要实现的是ConfigBuilder公开了一种方法build,该方法始终执行以下步骤:验证参数(如果无效,则抛出异常)并构建Config。当然,我想用最少的代码重复做到这一点。实际上,构建方法可以理想地分为两部分:Config的所有实现共享的参数的通用构建,以及每个Config的特定于实现的构建。

这是超类的一个例子

abstract class Config {
    def name: String
    def query: String
    def sourceTable: String
}

abstract class ConfigBuilder {
    // common variables are set through setters by the user, which finally calls build

    def build = {
        validate
        val sourceTable = extractFrom(query) // private local method

        // it will contain more fields, extracted from the ones set by the user 
        buildInternal(sourceTable)
    }

    def validate = {
        if(name == null) throw new Exception() // and all common checks 
    }
    abstract def buildInternal(s:String): Config  
}

这是一个实现

case class Factlog private ( 
    name:String, query:String, sourceTable:String, description: String)

class FactlogBuilder extends ConfigBuilder {
    // description is set through setters by the user

    def validate = { 
        super.validate()
        if(description == null) throw new Exception()
    }

    def buildInternal(s:String) = 
        Factlog(name,query,s,description)
}

此代码段有效,但我想了解这是否是实现buildbuildInternal方法的最佳方法。

  1. 通过这种方法,buildInternal签名将随任何新的Factlog特定参数而变化,因此解决方案是将sourceTable的计算结果放到ConfigBuilder中,方法构建之外
  2. 如果这样做,我将不得不在调用验证之前生成sourceTable
  3. 作为最后一种方法,我可以将外部变量实例化为var sourceTable = _,然后在验证方法调用之后,为其提供方法extractQuery返回的值

我很想使用方法3,但是我认为这并不是应该如何使用Scala。我相信,有更好的方法来构成这些层次结构。

P.S。参数列表肯定会随着时间增长,所以这是我必须考虑的问题。而且,Spark功能促进了构建器模式的使用,目前我无法避免使用它。

0 个答案:

没有答案