Kotlin 实现空对象模式

Kotlin 实现空对象模式,kotlin,null-object-pattern,Kotlin,Null Object Pattern,我发现它以某种方式在Kotlin中实现了空对象模式。我通常在Java中做一些不同的事情: class MyClass { static final MyClass INVALID = new MyClass(); public MyClass() { // empty } } 这样,我就可以始终使用MyClass.INVALID作为空对象 我如何在Kotlin实现这种风格 我摆弄过这样的东西: data class MyClass(val id: Int

我发现它以某种方式在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 {
    }
}
interface MyClass {
    val id: Int

    object INVALID : MyClass {
        override val id: Int = -1
    }
}

data class RealMyClass(override val id: Int) : MyClass

但这甚至不能编译。

您走的是正确的道路,这样做的问题是无法从数据类继承

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

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

    object INVALID : MyClass {
        override val id: Int = -1
    }
}

data class RealMyClass(override val id: Int) : MyClass
或者有一个可以继承的
开放类
,作为基类,这给了您更简洁的代码,因为在空对象的情况下,您可以重用基类中声明的属性-您仍然需要在数据类中重写它,因为所有数据类构造函数参数都需要是属性

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

data class RealMyClass(override val id: Int) : MyClass(id)

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

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
,以将其生成为真正的静态成员


我喜欢这个版本,因为不需要(在我看来是不必要的)继承。