【问题标题】:Implement null object pattern实现空对象模式
【发布时间】:2019-03-03 20:17:00
【问题描述】:

我发现this question 以某种方式在 Kotlin 中实现了空对象模式。我通常在 Java 中做的有点不同:

class MyClass {
    static final MyClass INVALID = new MyClass();

    public MyClass() {
       // empty
    }
}

这样,我总是可以使用MyClass.INVALID作为空对象。

如何在 Kotlin 中实现这种风格?

我摆弄了这样的东西:

data class MyClass(val id: Int) {
    object INVALID: MyClass {
    }
}

但这甚至无法编译。

【问题讨论】:

    标签: kotlin null-object-pattern


    【解决方案1】:

    实现此目的的一种方法是使用companion object。因为可以通过简单地使用类名作为限定符来调用伴生对象的成员。你可以这样做;

    data class MyClass(val id: Int) {
        companion object {
            @JvmStatic
            val nullInstance = MyClass(0)  //0 or any intended value
        }
    }
    
    //invocation
     val a = MyClass.nullInstance
     val b = MyClass.nullInstance
     print(a == b) //prints true because these are equavalent to Java's static instances.
    
    

    在这里,我将 nullInstance 注释为 @JvmStatic 以使其生成为真正的静态成员。

    https://kotlinlang.org/docs/reference/object-declarations.html

    【讨论】:

    • 我喜欢这个版本,因为不需要(在我看来是不必要的)继承。
    【解决方案2】:

    你在正确的轨道上,你会遇到的问题是你不能从数据类继承。

    您可以重组代码以使用接口,如下所示:

    interface MyClass {
        val id: Int
    
        object INVALID : MyClass {
            override val id: Int = -1
        }
    }
    
    data class RealMyClass(override val id: Int) : MyClass
    

    或者有一个可以继承的open class 作为基类,这为您提供了更简洁的代码,因为您可以在 null 对象的情况下重用基类中声明的属性 - 您仍然有在您的数据类中覆盖它,因为所有数据类构造函数参数都需要是属性。

    open class MyClass(open val id: Int) {
        object INVALID : MyClass(-1)
    }
    
    data class RealMyClass(override val id: Int) : MyClass(id)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      相关资源
      最近更新 更多