Hi all, is it possible to rewrite this in a better...
# codereview
j
Hi all, is it possible to rewrite this in a better way?
Copy code
fun SomeEnum.getImageRes(
    param: SomeOtherEnum
): Int {
    return when (param) {
        SomeOtherEnum.OtherEnumA -> {
            when (this) {
                SomeEnum.EnumA -> R.drawable.res1_a
                SomeEnum.EnumB -> R.drawable.res1_b
            }
        }
        SomeOtherEnum.OtherEnumB -> {
            when (this) {
                SomeEnum.EnumA -> R.drawable.res2_a
                SomeEnum.EnumB -> R.drawable.res2_b
            }
        }
    }
}
j
If this resource is really tied semantically to at least one of the enums, you could store in this enum a map from the other enum's values to the corresponding resource name
Could you share the real life names of these things?
p
personally I find a single truth table clearer to reason about than the nested whens
🙏 1
j
@Joffrey sure
Copy code
fun PlatformType.getEnrollmentImageRes(
    enrollmentType: EnrollmentType
): Int {
    return when (enrollmentType) {
        EnrollmentType.SDK -> {
            when (this) {
                PlatformType.GOOGLE_FIT -> R.drawable.google_fit_enrollment
                PlatformType.FITBIT -> R.drawable.fitbit_enrollment
            }
        }
        EnrollmentType.SIGN_UP -> {
            when (this) {
                PlatformType.GOOGLE_FIT -> R.drawable.google_fit_connection
                PlatformType.FITBIT -> R.drawable.fitbit_connection
            }
        }
    }
}
do you mean something like this?
Copy code
enum class PlatformType {
    GOOGLE_FIT {
        val enrollmentImageRes = mapOf(
            EnrollmentType.SDK to R.drawable.google_fit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.google_fit_connection
        )
    },
    FITBIT {
        val enrollmentImageRes = mapOf(
            EnrollmentType.SDK to R.drawable.fitbit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.fitbit_connection
        )
    }
}
j
Somewhat yes, although you should define the property itself on the enum type, not on each individual value (so it can always be called on a value of type
PlatformType
, not only on specific values like
PlatformType.GOOGLE_FIT
):
Copy code
enum class PlatformType(val enrollmentImageRes: Map<EnrollmentType, Int>) {
    GOOGLE_FIT(
        mapOf(
            EnrollmentType.SDK to R.drawable.google_fit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.google_fit_connection
    	)
    ),
    FITBIT(
        mapOf(
            EnrollmentType.SDK to R.drawable.fitbit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.fitbit_connection
        )
    )
}
Also given how your types maybe you could do the opposite and define those maps in the
EnrollmentType
enum instead, with
PlatformType
as key (if the
PlatformType
enum is used in other contexts than the enrollment-related things).
j
Yeah you're right, the `PlatformType`'s constructor is used in several other contexts, but I think that defining the maps in
EnrollmentType
wouldn't be as semantically correct, because those resources are representations of each
PlatformType
. What do you think about this?
Copy code
enum class PlatformType {
    GOOGLE_FIT {
        override val resMap = mapOf(
            EnrollmentType.SDK to R.drawable.google_fit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.google_fit_connection
        )
    },
    FITBIT {
        override val resMap = mapOf(
            EnrollmentType.SDK to R.drawable.fitbit_enrollment,
            EnrollmentType.SIGN_UP to R.drawable.fitbit_connection
        )
    };

    abstract val resMap: Map<EnrollmentType, Int>

}
that way I can always access the property for any
PlatformType
j
But why not use it on the constructor like I did above? You cannot use the constructor of an enum anywhere else anyway so why complicate things?
j
I was thinking of enum constructors as regular constructors where you'd have to update every instance creation, but that's not the case with enums. you're right. Although if I were to perform more complex validations based on parameters then I could have an abstract function that each enum can override, don't you think?
j
The validation would likely be the same for all enum values, right? So in that case I would just add an
init
block to the enum class, but still use the constructor I think. Of course it may depend on the use-case at hand
🙏 1