https://kotlinlang.org logo
Title
d

dave08

10/10/2018, 12:56 PM
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

miha-x64

10/10/2018, 1:06 PM
Consider implementing an interface with this property by all these enums.
👍 1
d

dave08

10/10/2018, 1:21 PM
Right, but how would I retreive all the entries?
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

David W

10/10/2018, 1:23 PM
(it as RestrictionKey).key
?
d

dave08

10/10/2018, 1:25 PM
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

David W

10/10/2018, 1:28 PM
Would you be able to do
val restrictionTypes = (VRestrictions.values() + YRestrictions.values()).map { (it as RestrictionKey).key } }
d

Dico

10/10/2018, 1:29 PM
val values = arrayOf<RestrictionKey>(*enumValues<VRestrictions>(), *enumValues<YRestrictions>())
d

David W

10/10/2018, 1:29 PM
means you don't have the actual enums in the list
d

Dico

10/10/2018, 1:30 PM
You can't just concatenate the arrays, but you can use spread operator like what I showed
d

David W

10/10/2018, 1:32 PM
oh
val restrictionTypes = (VRestrictions.values().toList() + YRestrictions.values()).map { (it as RestrictionKey).key } }
m

miha-x64

10/10/2018, 1:34 PM
You can't just concatenate the arrays
AFAIK, you can do both.
d

Dico

10/10/2018, 1:34 PM
No you definitely can't concatenate two arrays with different element types.
d

David W

10/10/2018, 1:34 PM
need to convert the array to a list before you can concat
but that's just an implementation detail
d

Dico

10/10/2018, 1:35 PM
it's a way to do it.
m

miha-x64

10/10/2018, 1:37 PM
BTW,
enumValues<T>
is reflective,
T.values()
is not.
d

Dico

10/10/2018, 1:38 PM
what makes it reflective?
d

dave08

10/10/2018, 1:39 PM
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

Dico

10/10/2018, 1:40 PM
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

miha-x64

10/10/2018, 1:41 PM
what makes it reflective?
My bad it's not. I thought it uses Java's
getEnumConstants()
, but it doesn't.
d

Dico

10/10/2018, 1:46 PM
@dave08 Consider somethinglike this:
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

David W

10/10/2018, 1:47 PM
Isn't the problem already solved?
d

dave08

10/10/2018, 1:50 PM
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

miha-x64

10/10/2018, 1:50 PM
d

David W

10/10/2018, 1:51 PM
or just use
A.values().toList() + B.values()
d

Dico

10/10/2018, 1:56 PM
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

miha-x64

10/10/2018, 1:57 PM
I wonder why don't Kotlin use
Object[]
array type everywhere
d

Dico

10/10/2018, 1:58 PM
Probably for the purpose of Java interoperability.