首页 > 解决方案 > 在 Kotlin 中,是否可以为不同的对象设置不同的枚举值,类似于 Python 处理枚举值的方式?

问题描述

我想在 Kotlin 中创建一个接受 RGB 值的颜色类。我还计划添加十六进制值,但这与问题无关。那我就上两节课。

data class RGB(val red: Int, val green: Int, val blue: Int)

RGB 类只存储三个整数。

class Color(rgb: RGB)

Color 类只存储一个 RGB 值。(我这样做是因为我计划向 Color 添加一个辅助构造函数,而不是一个十六进制对象。)

我想要一个存储几种通用颜色的枚举,但我希望枚举中的每个值实际上都是一个颜色对象,而不仅仅是存储一个。我当前的颜色枚举如下。

enum class Colors(color: Color) {

    WHITE(Color(RGB(255,255,255))),
    //Some other colors
    BLACK(Color(RGB(0,0,0)));

}

我遇到的问题是我无法将这些值传递给颜色参数或设置与它们相等的颜色对象(因为它们不是颜色,只是存储它们)。

在 Python 中,对于枚举,您实际上可以将枚举值设置为对象,因此可以用来代替该类型的任何对象。我不记得确切的语法,但它是类似的东西

class Colors(enum) {

    WHITE = Color(RGB(255,255,255)),
    //Some other colors
    BLACK = Color(RGB(0,0,0));

}

这样,如果我有一些带有颜色类型参数的方法

//We've moved back into Kotlin
fun someMethod(color: Color) {
    //Color some stuff
}

我实际上可以从枚举中传入一个对象。

someMethod(Colors.WHITE)

我知道使用我当前的 Kotlin 枚举,我可以调用 Colors.WHITE.color 但我只想知道我是否可以用 Python 的方式来做。我的颜色枚举只是一个例子,但我还有其他更重要的用途。

TL;DR 我希望能够通过将它们设置为对象来对单个枚举值使用多态性。我希望能够通过将它们设置为 X(parameters) 来将它们传递给 X 类型的参数

标签: kotlinenumspolymorphism

解决方案


我经常看到人们使用枚举作为定义一些常量的一种方式——他们不一定想利用一些序数值或封闭的成员集。

如果您想利用 Enum 类型事物的一组封闭成员属性,那么 asealed class可能是您的解决方案。密封类具有一组固定的实现,因此您可以拥有诸如 switch/when 语句之类的东西,这些语句知道它们已经对集合中的所有情况进行了说明。

顺便说一句,这个属性是sealed class实现 agebraic 数据类型的完美工具的原因,它可以让您处理可能是几个完全不同的事物之一安全的值。Eunms 都是相同的东西并且具有相同的功能,sealed class可以由没有共同点的对象和实例组成。

这是一个例子。

import java.awt.Color

sealed class MyColor(r: Int, g: Int, b: Int) : Color(r, g, b) {
    object WHITE : MyColor(255, 255, 255)
    object BLACK : MyColor(0, 0, 0)
}

fun doSomethingWithAColor(color: Color) {
    //Your Stuff
}

fun main() {
    val color: MyColor = MyColor.WHITE
    // This when clause is able to know that it has handled every case or not
    when (color) {
        MyColor.WHITE -> doSomethingWithAColor(color)
        MyColor.BLACK -> doSomethingWithAColor(color)
    }
}

如果您真正想要的只是一组常量,则sealed class解决方案提供了这一点,但是具有不可变成员和私有构造函数的普通旧静态类就可以了。这是一个示例,它的工作方式与上面的示例相同。

class MyColor private constructor(r: Int, g: Int, b: Int): Color(r,g,b){
    companion object{
        val WHITE = MyColor(255, 255, 255)
        val BLACK = MyColor(0, 0, 0)
    }
}

如果您确实想利用 Enum 的序数值(但从您的 python 示例中我不认为您这样做),那么恐怕我没有现成的解决方案。我认为您只需要在顶级类上提供更多自定义函数来模仿这种数字到实例的映射并具有您正在寻找的类型继承。


推荐阅读