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

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

主站蜘蛛池模板: 介休市| 漳浦县| 昭苏县| 富锦市| 岑溪市| 金山区| 乌鲁木齐市| 梨树县| 屏东县| 中山市| 巴彦县| 南郑县| 沾化县| 昭苏县| 高雄市| 乐清市| 贞丰县| 孟连| 南靖县| 咸丰县| 丰原市| 郁南县| 紫云| 象州县| 武安市| 周宁县| 从化市| 华坪县| 麟游县| 庐江县| 黑河市| 苏尼特左旗| 潞西市| 九寨沟县| 改则县| 遂溪县| 林西县| 天台县| 邢台县| 巫山县| 凤台县|