Reputation: 403
I want to create a color class in Kotlin, that takes in an RGB value. I also plan on adding hex values but that doesn't pertain to the question. I would have two classes, then.
data class RGB(val red: Int, val green: Int, val blue: Int)
The RGB Class just stores three ints.
class Color(rgb: RGB)
The Color class just stores an RGB value. (I'm doing it this way because I plan to add a secondary constructor to Color that excepts a hex object instead.)
I want to have an enumeration that stores several generic colors, but I want each value in the enum to actually be a color object, not just store one. My current Colors enum is as follows.
enum class Colors(color: Color) {
WHITE(Color(RGB(255,255,255))),
//Some other colors
BLACK(Color(RGB(0,0,0)));
}
The issue I have with this is that I can't pass these values into a color parameter or set a color object equal to them (because they aren't colors, and just store them).
In Python, for enumerations, you can actually set enum values as objects, and therefore can be used in place of any object of that type. I don't remember the syntax exactly, but it was something along the lines of
class Colors(enum) {
WHITE = Color(RGB(255,255,255)),
//Some other colors
BLACK = Color(RGB(0,0,0));
}
This way if I have some method with a parameter of type color
//We've moved back into Kotlin
fun someMethod(color: Color) {
//Color some stuff
}
I can actually pass in an object from the enum.
someMethod(Colors.WHITE)
I am aware that using my current Kotlin enum, I can just call Colors.WHITE.color but I just want to know if I can do it the Python way. My Colors enum is just an example, but I have other uses where it is more important.
TL;DR I want to be able to use polymorphism on individual enum values, by setting them equal to objects. I want to be able to pass them into parameters of type X by setting them equal to X(parameters)
Upvotes: 1
Views: 3426
Reputation: 1676
I often see that people use an Enum as a way of defining some constants - they do not necessarily want to take advantage of some ordinal value, or the closed set of members.
If you want to take advantage of a closed set of members property of an Enum type thing, then a sealed class
could be your solution. A sealed class has a fixed set of implementations, so you can have things like switch/when statements that know they have exhuasted all cases in the set.
As an aside, this property is what makes sealed class
the perfect tool for implementing aglebraic data types in a way that keeps your handling of a value that could be one of several completely different things safe. Eunms are all the same thing and have the same functions, a sealed class
could consist of objects and instances that have nothing in common.
Here is an example.
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)
}
}
If all you actually want is a set of constants, the sealed class
solution provides that, but a normal old static class with immutable members and a private constructor will do. Here is an example, and it will work the same way as the example above.
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)
}
}
If you do want to take advantage of an Enum's ordinal value (but from your python example I don't think you do) then I am afraid I am out of solutions that come out of the box. I think you would need to just provide more custom functions on your top level class to mimic that sort of number to instance mapping and have the type inheritance you are looking for.
Upvotes: 1