Why can't I check at runtime if `Listener<T>...
# announcements
z
Why can't I check at runtime if
Listener<T>
is
Listener<User>
?
z
So there's no way to check for this?
k
Maybe you can hack something together using reified functions, depends on your use case.
z
fun <T> subscribe(topic: Topic, listener: Listener<T>)
d
You can make the function
inline
and the type parameter
reified
, then you can do checks on
T::class
.
z
For each topic there's a specific T that is acceptable
a
if its the use-case from earlier, there is no way to do that without unsafe casts
d
In that case
Topic
should have a
<T>
as well.
a
and to compare types you need to use
KClass
z
Yes, same, I was searching for the least ugly way to do this
a
because of type erasure there is no safe way to do that unfortunately
z
๐Ÿ˜•
d
If
Topic
has a type parameter as well, then it will be checked at compile time.
z
But
Topic
is an
enum
...
d
Maybe it should be a
sealed class
then ๐Ÿ˜‰
z
Copy code
@Suppress("unused")
sealed class TopicWrapper<T>

class UserTopicWrapper : TopicWrapper<User>() {
    companion object {
        val INSTANCE = UserTopicWrapper()
    }
}
...
Copy code
fun <T> subscribe(topic: TopicWrapper<T>, listener: Listener<T>) {
        when (topic) {
            is UserTopicWrapper -> {
                @Suppress("UNCHECKED_CAST")
                userListeners.add(listener as Listener<User>)
            }
        }
    }
Something like this?
d
Why not
object UserTopicWrapper : TopicWrapper<User>()
?
z
Very cool ๐Ÿ˜„
Some other edits?
d
You could out-source the adding to the
Topic
instance, then you would save yourself the unchecked cast.
But other than that, looks alright
z
Mm so you'd move the listeners to
TopicWrapper
?
Yeah you avoid the unchecked cast but then everybody can touch the listeners variable right?
d
No, not really. I am not 100% sure of your setup, but something like this:
Copy code
sealed class TopicWrapper<T> {
    abstract fun addListener(listener: Listener<T>, userListeners: MutableList<Listener<User>>, otherListeners: MutableList<Listener<Other>>
}
And then implement that in the respective topic-wrapper object.
Like so:
Copy code
object UserTopic : TopicWrapper<User> {
    override fun addListener(listener: Listener<User>, userListeners: MutableList<Listener<User>>, otherListeners: MutableList<Listener<Other>> {
        userListeners += listener
    }
No unchecked cast anywhere ๐Ÿ˜‰
a
and then he ends up with a property per type which he tried to avoid ^^
d
userListeners.add(listener as Listener<User>)
That suggests otherwise...
z
If I do it like this I can just create N functions for N types
Which I will do because I've lost enough time on this for today ๐Ÿ˜„
a
d
Ah, yes okay. Then there is no way to avoid the unchecked cast. Sorry ๐Ÿ™ˆ
a
@ziggy42 what is more important to you? having one list per type or using an unchecked cast?
z
I'd prefer to avoid the unchecked cast