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

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

主站蜘蛛池模板: 阿拉善左旗| 万荣县| 芷江| 岑巩县| 东乡族自治县| 沛县| 彰化县| 龙门县| 故城县| 辰溪县| 当涂县| 繁峙县| 汝城县| 宁晋县| 青川县| 柘荣县| 靖西县| 游戏| 黄梅县| 彭阳县| 邳州市| 三明市| 焦作市| 昭觉县| 南华县| 新竹县| 张北县| 崇明县| 临城县| 玉树县| 佛教| 仙居县| 凤山县| 怀化市| 赣榆县| 宁陕县| 乡城县| 南召县| 霸州市| 古蔺县| 茶陵县|