【问题标题】:How to write a base class for DRY in this situation without DI in Kotlin?在没有 DI 的情况下,如何在 Kotlin 中为 DRY 编写基类?
【发布时间】:2018-03-21 03:32:30
【问题描述】:

我有一堂课有2个案例,一个是这样的:

class User {
    private val name:Name = NameGenerator()

    fun sayName() {
        println(this.name.fakeName)
    }
}

另一个是:

class User(suggestion:String) {
    private val name:Name = NameGenerator(suggestion)

    fun sayName() {
        println(this.name.fakeName)
    }
}

现在你看到了不同之处,这就是name,它有两种不同的初始化方式。

在这种情况下,我如何为 DRY 编写一个基类?

我最终得到了这样的结果:

abstract class BaseUser {
    protected val name:Name = MockName()

    fun sayName() {
        println(this.name.fakeName)
    }
}

然后我可以像这样使用它:

class UserCaseOne():BaseUser() {

}

class UserCaseTwo(suggestion:String):BaseUser() {
    init {
        this.name = NameGenerator(suggestion)
    }
}

考虑到我必须使用模拟对象来初始化,这很糟糕。

有没有更好的方法来做到这一点?不注入实现?我不想强制 UserCaseTwo 有一个冗余的构造函数。

【问题讨论】:

    标签: kotlin jvm refactoring dry


    【解决方案1】:

    如果您的目标本质上是两个,将前两个 User 类合并为一个类,您可以这样做:

    class User(suggestion: String? = null) {
        private val name: NameGenerator = suggestion?.let { NameGenerator(it) } ?: NameGenerator()
    
        fun sayName() {
            println(this.name.fakeName)
        }
    }
    

    【讨论】:

    • 感谢您的帮助。但我想我不能这样做。因为例子有点简单,而在实际代码中,caseOne和caseTwo将在2个jar文件中,其中suggestion是一个类,不能出现在caseOne jar文件中。
    【解决方案2】:

    通过将函数作为参数将名称配置作为构造函数签名的一部分是否可以接受?以下方法可以实现所需的抽象恕我直言:

    class User(private val nameProvider: () -> Name) {
        private val name: Name by lazy(nameProvider)
    
        fun sayName() {
            println(this.name.fakeName)
        }
    } 
    

    您可以使用任何nameProvider 创建Users,例如:

    User { MockName() }
    User { NameGenerator("blah") }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 2019-11-01
      • 1970-01-01
      相关资源
      最近更新 更多