Kotlin 枚举中的循环引用

Circular reference in Kotlin Enum

如何创建带有循环引用的枚举 class?

简单示例(取自):

enum class Hand(val beats: Hand) {
    ROCK(SCISSORS), // Enum entry 'SCISSORS' is uninitialized here
    PAPER(ROCK),
    SCISSORS(PAPER);
}

由于 val 属性禁止重新分配,所以这个问题通常很难解决,通常表明您的数据模型存在问题。有关更广泛背景下的讨论,请参阅 .

然而,这个简单的例子可以使用 val property with custom getter (thus without a backing field). Using when 来解决,getter 可以用一种非常可读的方式定义:

enum class Hand {
    ROCK,
    PAPER,
    SCISSORS;

    val beats: Hand
        get() = when (this) {
            ROCK -> SCISSORS
            PAPER -> ROCK
            SCISSORS -> PAPER
        }
}

另一种解决方案(类似于 ) is to use sealed classes。由于概念约束较少,与 enum 具有覆盖的属性。

sealed class Hand {
    abstract val beats: Hand

    object ROCK: Hand() {
        override val beats = SCISSORS
    }

    object PAPER: Hand() {
        override val beats = ROCK
    }

    object SCISSORS: Hand() {
        override val beats = PAPER
    }
}

1个人意见

免责声明:我没有关于这些解决方案如何与经典 Java 结合使用的信息。

没有流控制语句的 mhoff 答案的替代方法:

enum class Hand {
    ROCK {
        override val beats: Hand
            get() = SCISSORS
    },
    PAPER {
        override val beats: Hand
            get() = ROCK
    },
    SCISSORS {
        override val beats: Hand
            get() = PAPER
    };

    abstract val beats: Hand
}

在当前的 Kotlin 中,您可以将 vals 与密封的 class 一起使用,就像 enum:

一样
sealed class Hand(val beats: Hand) {
    object ROCK : Hand(SCISSORS)
    object PAPER : Hand(ROCK)
    object SCISSORS : Hand(PAPER)
}

循环引用仍然存在,但不会造成任何问题。

这很奇怪,因为它与 enum 几乎相同,但没有自动序列化。