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

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).

主站蜘蛛池模板: 曲松县| 六枝特区| 洪泽县| 嫩江县| 大余县| 巩留县| 墨玉县| 渭源县| 宕昌县| 贺州市| 双城市| 宿迁市| 宁德市| 辽阳市| 丹阳市| 栾城县| 九龙县| 襄垣县| 安乡县| 静乐县| 文安县| 本溪市| 仁寿县| 白山市| 永平县| 始兴县| 德令哈市| 嫩江县| 长泰县| 通城县| 永寿县| 娱乐| 高淳县| 定安县| 长寿区| 台北县| 闻喜县| 依兰县| 黄浦区| 瑞安市| 库车县|