Reputation: 198
The following enum definition is valid. Is it possible to access the "inner property" auditData or function auditor?
enum class GWGStatus {
UNCHECKED,
CHECKED {
lateinit var auditDate: Date
fun auditor() : String = "Peter"
}
}
GWGStatus.CHECKED.??? (does not work)
Upvotes: 5
Views: 6376
Reputation: 23242
As soon as I saw this I just needed to look up the bytecode as I couldn't imagine what this should be translated to. While I believe "it" is a bug, I will show you what I found out so far.
For CHECKED
there is actually created its own subclass, i.e. public final class GWGStatus$CHECKED extends GWGStatus
even though GWGStatus
is an enum itself. Probably again something that is allowed in the JVM bytecode, but isn't allowed in the Java language specification.
Now comes the not-so-congruent part. While the following works in Java:
GWGStatus.CHECKED status = (GWGStatus.CHECKED) GWGStatus.CHECKED;
status.auditDate = new Date();
System.out.println(status.auditor());
and prints Peter
as expected, the cast isn't possible in Kotlin (yet?):
GWGStatus.CHECKED as GWGStatus.CHECKED // fails: Use of enum entry names as types is not allowed, use enum type instead
Now using java reflection utilities in Kotlin (e.g. status::class.java.declaredFields
or .java.declaredMethods
) both auditor()
and getAuditDate()
(etc.) are visible and accessible (as was already proven by the Java code itself). Analysing further and just using Kotlin reflection instead:
GWGStatus.UNCHECKED::class // returns class GWGStatus
GWGStatus.CHECKED::class // return class GWGStatus$CHECKED ... that's good so far
GWGStatus.CHECKED::class.declaredMembers // empty list ... didn't expect this one
// empty too: GWGStatus.CHECKED::class.declaredMemberProperties
// and GWGStatus.CHECKED::class.declaredFunctions
GWGStatus.CHECKED::class.superTypes // shows GWGStatus as expected
GWGStatus.CHECKED::class.members // shows clone(), finalize(), name, equals, hashcode, tostring, getdeclaringclass, ordinal... nothing we are interested in and rather the ~general enum members
GWGStatus::class.nestedClasses // empty too
Ok... we can't see them using Kotlin reflection (or maybe I did not use the right approach? ;-)). So: something smells like a bug here, but I am not sure yet what the bug is:
Upvotes: 4
Reputation: 2937
You can also just use the constructor:
enum class GWSGStatus(var date: Date, private var auditor: String) {
UNCHECKED(Date(), ""),
CHECKED(Date(), "Peter");
fun auditor() = auditor
}
It still depends on the usage of this enum. Pay attention to previous post
Upvotes: 0
Reputation: 97130
You would have to declare the variables and functions in the enum
type itself and then override them in the enum
instances.
Unfortunately, since not all your enum
instances implement the function, you can't make it abstract
and have to provide a default implementation:
import java.util.*
enum class GWGStatus {
UNCHECKED,
CHECKED {
override lateinit var auditDate: Date
override fun auditor(): String = "Peter"
};
open lateinit var auditDate: Date
open fun auditor(): String = ""
}
fun main(vararg args: String) {
GWGStatus.CHECKED.auditDate = Date()
println(GWGStatus.CHECKED.auditDate)
println(GWGStatus.CHECKED.auditor())
}
Note however, that this enum
usage feels really strange. You're storing state data in something that is intended to be a constant object. There will only ever be one GWGStatus.CHECKED
object in memory, so it doesn't seem like the right place to store state information.
Upvotes: 3