官术网_书友最值得收藏!

Type smart casts

Let's represent the Animal and Fish classes from the previous section:

Let's assume we want to call the isHungry method and we want to check if the animal is an instance of Fish. In Java, we would have to do something like this:

    //Java 
    if (animal instanceof Fish){ 
        Fish fish = (Fish) animal; 
        fish.isHungry();      
        //or 
        ((Fish) animal).isHungry(); 
    } 

The problem with this code is its redundancy. We have to check if the animal instance is Fish and then we have to explicitly cast animal to Fish after this check. Wouldn't it be nice if the compiler could handle this for us? It turns out that the Kotlin compiler is really smart when it comes to casts, so it will handle all those redundant casts for us, using the smart casts mechanism. Here is an example of smart casting:

    if(animal is Fish) { 
        animal.isHungry() 
    } 
Smart casting in Android Studio
Android Studio will display proper errors if smart casting is not possible, so we will know exactly whether we can use it. Android Studio marks variables with a green background when we access a member that required a cast.

In Kotlin, we don't have to explicitly cast an animal instance to Fish, because after the type check, the Kotlin compiler will be able to handle casts implicitly. Now inside the if block, the variable animal is cast to Fish. The result is then exactly the same as in the previous Java example (the Java instance of the operator is called in Kotlin). This is why we can safely call the isHungry method without any explicit casting. Notice that in this case, the scope of this smart cast is limited by the if block:

    if(animal is Fish) { 
        animal.isHungry() //1 
    } 
 
    animal.isHungry() //2, Error 
  1. In this context, the animal instance is Fish, so we can call the isHungry method.
  2. In this context, the animal instance is still Animal, so we can't call the isHungry method.

There are, however, other cases where the smart cast scope is larger than a single block, as in the following example:

    val fish:Fish? = // ... 
    if (animal !is Fish) //1 
        return 
 
    animal.isHungry() //1 
  1. From this point, animal will be implicitly converted to a non-nullable Fish.

In the preceding example, the whole method would return from the function if animal is not Fish, so the compiler knows that animal must be Fish across the rest of the code block. Kotlin and Java conditional expressions are evaluated lazily.

This means that in the expression condition1() && condition2(), the method condition2 will be called only when condition1 returns true. This is why we can use a smart cast type on the right-hand side of the conditional expression:

    if (animal is Fish && animal.isHungry()) { 
        println("Fish is hungry") 
    } 

Notice that if the animal was not Fish, the second part of the conditional expression would not be evaluated at all. When it is evaluated, Kotlin knows that animal is Fish (smart cast).

主站蜘蛛池模板: 清丰县| 阜平县| 永年县| 昌平区| 图片| 满城县| 清水河县| 兴业县| 工布江达县| 许昌市| 桂平市| 平度市| 嘉鱼县| 高要市| 谢通门县| 东乡族自治县| 宁城县| 木兰县| 河津市| 河东区| 海原县| 洪雅县| 鹰潭市| 高平市| 沐川县| 安吉县| 平远县| 兰考县| 尖扎县| 西平县| 平定县| 神农架林区| 介休市| 淮北市| 英德市| 陆良县| 安新县| 闸北区| 霍城县| 定襄县| 富阳市|