Using Kotlin contracts to cast type inside Iterable function predicate

后端 未结 1 1541
我在风中等你
我在风中等你 2021-01-23 14:01

I have this sealed class PictureEvent:

sealed class PictureEvent {

    data class PictureCreated(val pictureId: String, val url: String) : PictureE         


        
相关标签:
1条回答
  • 2021-01-23 14:40

    The contract works fine, however if you take a look at the first method signature, you should be able to understand what is happening and why the found object isn't autocast:

    public inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T
    

    The return type of the first method is just the same as that defined for all elements in the Iterable instance, PictureEvent in your case, and no autocasting inside the predicate can unfortunately change that.


    Instead of contracts, for example, you can filter your list by the desired class type first, and then take the first element:

    val creationEvent = events
        .filterIsInstance(PictureEvent.PictureCreated::class.java)
        .first()
    

    or create your own extension similar to first:

    inline fun <reified R> Iterable<*>.firstOfInstance(): R {
        val first = first { it is R }
        return first as R
    }
    
    // or wrapping filterIsInstance
    inline fun <reified R> Iterable<*>.firstOfInstance(): R {
        return filterIsInstance(R::class.java).first()
    }
    
    val creationEvent = events.firstOfInstance<PictureEvent.PictureCreated>()
    
    0 讨论(0)
提交回复
热议问题