4.8.1 is,!is运算符
is运算符可以检查对象是否与特定的类型兼容(“兼容”的意思是:此对象是该类型,或者派生于该类型)。is运算符用来检查对象(变量)是否属于某数据类型(如Int、String、Boolean等)。C#里面也有这个运算符。
is运算符类似Java的instanceof:
@org.junit.runner.RunWith(org.junit.runners.JUnit4.class)
public class TypeSystemDemo {
    @org.junit.Test
    public void testVoid() {
        if ("abc" instanceof String) {
            println("abc is instanceof String");
        } else {
            println("abc is not instanceof String");
        }
    }
    void println(Object obj) {
        System.out.println(obj);
    }
}
在Kotlin中,我们可以在运行时通过使用 is 操作符或其否定形式 !is 来检查对象是否符合给定类型:
>>> "abc" is String
true
>>> "abc" !is String
false
>>> null is Any
false
>>> null is Any?
true
代码示例:
@RunWith(JUnit4::class)
class ASOperatorTest {
    @Test fun testAS() {
        val foo = Foo()
        val goo = Goo()
        println(foo is Foo) //true 自己
        println(goo is Foo)// 子类 is 父类 = true
        println(foo is Goo)//父类 is 子类 = false
        println(goo is Goo)//true 自己
    }
}
open class Foo
class Goo : Foo()
类型自动转换
在Java代码中,当我们使用str instanceof String来判断其值为true的时候,我们想使用str变量,还需要显式的强制转换类型:
@org.junit.runner.RunWith(org.junit.runners.JUnit4.class)
public class TypeSystemDemo {
    @org.junit.Test
    public void testVoid() {
        Object str = "abc";
        if (str instanceof String) {
            int len = ((String)str).length();  // 显式的强制转换类型为String
            println(str + " is instanceof String");
            println("Length: " + len);
        } else {
            println(str + " is not instanceof String");
        }
        boolean is = "1" instanceof String;
        println(is);
    }
    void println(Object obj) {
        System.out.println(obj);
    }
}
而大多数情况下,我们不需要在 Kotlin 中使用显式转换操作符,因为编译器跟踪不可变值的 is-检查,并在需要时自动插入(安全的)转换:
@Test fun testIS() {
    val len = strlen("abc")
    println(len) // 3
    val lens = strlen(1)
    println(lens) // 1
}
fun strlen(ani: Any): Int {
    if (ani is String) {
        return ani.length
    } else if (ani is Number) {
        return ani.toString().length
    } else if (ani is Char) {
        return 1
    } else if (ani is Boolean) {
        return 1
    }
    print("Not A String")
    return -1
}
4.8.2 as运算符
as运算符用于执行引用类型的显式类型转换。如果要转换的类型与指定的类型兼容,转换就会成功进行;如果类型不兼容,使用as?运算符就会返回值null。
代码示例:
>>> open class Foo
>>> class Goo:Foo()
>>> val foo = Foo()
>>> val goo = Goo()
>>> foo as Goo
java.lang.ClassCastException: Line69$Foo cannot be cast to Line71$Goo
>>> foo as? Goo
null
>>> goo as Foo
Line71$Goo@73dce0e6
我们可以看出,在Kotlin中,子类是禁止转换为父类型的。
按照Liskov替换原则,父类转换为子类是对OOP的严重违反,不提倡、也不建议。严格来说,父类是不能转换为子类的,子类包含了父类所有的方法和属性,而父类则未必具有和子类同样成员范围,所以这种转换是不被允许的,即便是两个具有父子关系的空类型,也是如此。