Is there a way to have a `List` of a few different...
# announcements
d
Is there a way to have a
List
of a few different enums with a common property
val
? I'd need to be able to retreive the list of entries and get the value of that property for each...
m
Consider implementing an interface with this property by all these enums.
👍 1
d
Right, but how would I retreive all the entries?
Copy code
interface RestrictionKey {
	val key: String
}

enum VRestrictions(name: String): RestrictionKey {
      ONE("one"), TWO("two");

      override val key = "pr.$name"
}

enum YRestrictions(name: String): RestrictionKey {
      THREE("three"), FOUR("four");

      override val key = "pr.$name"
}
val restrictionTypes = listOf(VRestrictions, YRestrictions).flatMap { it.entries.map { it.key } }
I need something like that, but how would I get the entries...?
d
(it as RestrictionKey).key
?
d
Right, but that's not the main problem... When VRestrictions derives from RestrictionKey, it's really its elements that derive from it, not the enum itself. The enum itself has the
entries
property that I can't access...
d
Would you be able to do
Copy code
val restrictionTypes = (VRestrictions.values() + YRestrictions.values()).map { (it as RestrictionKey).key } }
d
Copy code
val values = arrayOf<RestrictionKey>(*enumValues<VRestrictions>(), *enumValues<YRestrictions>())
d
means you don't have the actual enums in the list
d
You can't just concatenate the arrays, but you can use spread operator like what I showed
d
oh
val restrictionTypes = (VRestrictions.values().toList() + YRestrictions.values()).map { (it as RestrictionKey).key } }
m
You can't just concatenate the arrays
AFAIK, you can do both.
d
need to convert the array to a list before you can concat
d
No you definitely can't concatenate two arrays with different element types.
d
but that's just an implementation detail
d
it's a way to do it.
m
BTW,
enumValues<T>
is reflective,
T.values()
is not.
d
what makes it reflective?
d
I really need to pass these to a
RestrictionsStore
to validate all the possible keys coming in from an API before being saved... so maybe not necessary to pass the actual enums in that case. Reflective meaning using reflection to get the values?
d
enumValues<T>
exists to be able to get the
values()
of a
reified
type parameter. It is inlined by the compiler and produces exactly the same call.
m
what makes it reflective?
My bad it's not. I thought it uses Java's
getEnumConstants()
, but it doesn't.
d
@dave08 Consider somethinglike this:
Copy code
interface RestrictionKey

    object RestrictionKeys {
        private val values = mutableListOf<RestrictionKey>()
        val allKeys: List<RestrictionKey> get() = values

        fun register(vararg keys: RestrictionKey) {
            // filter logic here
            values += keys
        }

        inline fun <reified T> register()
            where T : Enum<T>, T : RestrictionKey {
            register(*enumValues<T>())
        }
    }
    
    fun main() {
        RestrictionKeys.register<YRestrictions>()
        RestrictionKeys.register<VRestrictions>()
        
        for (key in RestrictionKeys.allKeys) {
            // use keys?
        }
    }
d
Isn't the problem already solved?
d
Thanks everybody! Those are both nice solutions, maybe one day there'll be some kind of base class for enums to make this even easier...
m
d
or just use
A.values().toList() + B.values()
d
I'm wondering that as well @miha-x64
The implementation (on the JVM) would have to change though.
It would have to reflectively find the first common superclass of the 2 arrays, because the generics are erased.
m
I wonder why don't Kotlin use
Object[]
array type everywhere
d
Probably for the purpose of Java interoperability.