syntax struggle, I have an enum class, which I wan...
# announcements
t
syntax struggle, I have an enum class, which I want to return an appropriate FragmentActivity subtype:
Copy code
val activity:KClass<FragmentActivity>
   get() {
      return when (this) {
         Single, SingleWithSense, SingleWithPeriod, Dual, Echo -> AllocatedNodeActivity::class
         Central -> CentralNodeActivity::class
         Unknown -> PristineNodeActivity::class
      }
   }
It just yells at me because none of the return types match the KClass<FragmentActivity> type. What's the secret sauce I'm missing?
s
first thought is to try changing the type to
KClass<out FragmentActivity>
🙏 1
👍 1
t
that works! so... what's the
out
do for me in that context?
s
How familiar are you with covariance and contravariance?
t
Not terribly. Thanks for the read. Kind of understand, kind of don't. I wish it talked less about Java, which I can read, but am not a hard core consumer of
s
Hmm, gimme a sec, I think there’s a better explainer out there
(shouldn’t have assumed you were familiar with java wildcards, my b)
https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance this article (which is technically focused on C# but it’s not hard to grok) goes over what covariance and contravariance are in more detail, but the tl;dr for your code is that, by default, the type parameter for a generic type is invariant, which means that when you’re assigning the variable or calling methods that use the generic type, you must supply exactly the type you specified — subtypes and supertypes are not allowed.
out
makes the parameter covariant, so you can use the type you specified and subtypes of it. This helps you because now you can safely opt into treating (for example) a
KClass<PristineNodeActivity>
like a
KClass<FragmentActivity>
We use
in
and
out
because Java’s wildcard projections (e.g.
? extends FragmentActivity
) are cumbersome, and we can relate the usage of the generic type to how we plan on using it (i.e. whether or not the object will consume (in) or produce (out) the type
t
Shawn, your explanation makes sense, thanks
👍 1