fun main() {
val input: Any = "Hello, Kotlin"
if (input is String) {
println("Message length: ${input.length}")
// 输出结果为: Message length: 13
}
if (input !is String) { // 等价于 !(input is String)
println("Input is not a valid message")
} else {
println("Processing message: ${input.length} characters")
// 输出结果为: Processing message: 13 characters
}
}
也可以使用 is 和 !is 操作符, 检查对象是否匹配某个子类型:
interface Animal {
val name: String
fun speak()
}
class Dog(override val name: String) : Animal {
override fun speak() = println("$name says: Woof!")
}
class Cat(override val name: String) : Animal {
override fun speak() = println("$name says: Meow!")
}
//sampleStart
fun handleAnimal(animal: Animal) {
println("Handling animal: ${animal.name}")
animal.speak()
// 使用 is 操作符检查子类型
if (animal is Dog) {
println("Special care instructions: This is a dog.")
} else if (animal is Cat) {
println("Special care instructions: This is a cat.")
}
}
//sampleEnd
fun main() {
val pets: List<Animal> = listOf(
Dog("Buddy"),
Cat("Whiskers"),
Dog("Rex")
)
for (pet in pets) {
handleAnimal(pet)
println("---")
}
// 输出结果为:
// Handling animal: Buddy
// Buddy says: Woof!
// Special care instructions: This is a dog.
// ---
// Handling animal: Whiskers
// Whiskers says: Meow!
// Special care instructions: This is a cat.
// ---
// Handling animal: Rex
// Rex says: Woof!
// Special care instructions: This is a dog.
// ---
}
这个示例使用 is 操作符检查, Animal 类实例是否为子类型 Dog 或 Cat, 来打印相关的护理说明.
fun processInput(data: Any) {
when (data) {
// data 被自动转换为 Int 类型
is Int -> println("Log: Assigned new ID ${data + 1}")
// data 被自动转换为 String 类型
is String -> println("Log: Received message \"$data\"")
// data 被自动转换为 IntArray 类型
is IntArray -> println("Log: Processed scores, total = ${data.sum()}")
}
}
fun main() {
processInput(1001)
// 输出结果为: Log: Assigned new ID 1002
processInput("System rebooted")
// 输出结果为: Log: Received message "System rebooted"
processInput(intArrayOf(10, 20, 30))
// 输出结果为: Log: Processed scores, total = 60
}
sealed interface Status
data class Ok(val currentRoom: String) : Status
data object Error : Status
class RobotVacuum(val rooms: List<String>) {
var index = 0
fun status(): Status =
if (index < rooms.size) Ok(rooms[index])
else Error
fun clean(): Status {
println("Finished cleaning ${rooms[index]}")
index++
return status()
}
}
fun main() {
//sampleStart
val robo = RobotVacuum(listOf("Living Room", "Kitchen", "Hallway"))
var status: Status = robo.status()
while (status is Ok) {
// 编译器将 status 智能类型转换为 OK 类型,
// 因此可以访问 currentRoom 属性.
println("Cleaning ${status.currentRoom}...")
status = robo.clean()
}
// 输出结果为:
// Cleaning Living Room...
// Finished cleaning Living Room
// Cleaning Kitchen...
// Finished cleaning Kitchen
// Cleaning Hallway...
// Finished cleaning Hallway
//sampleEnd
}
在这个示例中, 封闭接口 Status 有两个实现: 数据类 Ok 和数据对象 Error. 只有数据类 Ok 才有 currentRoom 属性. 当 while 循环条件计算结果为 true 时, 编译器将 status 变量智能类型转换为 Ok 类型, 使得循环体内可以访问 currentRoom 属性.
// 在 `||` 的右侧, x 被自动转换为 String 类型
if (x !is String || x.length == 0) return
// 在 `&&` 的右侧, x 被自动转换为 String 类型
if (x is String && x.length > 0) {
print(x.length) // x 被自动转换为 String 类型
}
如果你将对象的多个类型检查用 or 操作符 (||) 组合起来, 智能类型转换的结果会是这些类型最接近的共通超类型:
interface Status {
fun signal() {}
}
interface Ok : Status
interface Postponed : Status
interface Declined : Status
fun signalCheck(signalStatus: Any) {
if (signalStatus is Postponed || signalStatus is Declined) {
// signalStatus 被智能类型转换为共通超类型 Status
signalStatus.signal()
}
}
fun main() {
val rawInput: Any = "user-1234"
// 成功转换为 String 类型
val userId = rawInput as String
println("Logging in user with ID: $userId")
// 输出结果为: Logging in user with ID: user-1234
// 触发 ClassCastException
val wrongCast = rawInput as Int
println("wrongCast contains: $wrongCast")
// Exception in thread "main" java.lang.ClassCastException
}
fun main() {
val rawInput: Any = "user-1234"
// 成功转换为 String 类型
val userId = rawInput as? String
println("Logging in user with ID: $userId")
// 输出结果为: Logging in user with ID: user-1234
// 将 null 值赋给 wrongCast
val wrongCast = rawInput as? Int
println("wrongCast contains: $wrongCast")
// 输出结果为: wrongCast contains: null
}
interface Animal {
fun makeSound()
}
class Dog : Animal {
// 实现 makeSound() 的行为
override fun makeSound() {
println("Dog says woof!")
}
}
fun printAnimalInfo(animal: Animal) {
animal.makeSound()
}
fun main() {
val dog = Dog()
// 将 Dog 实例向上转换为 Animal
printAnimalInfo(dog)
// 输出结果为: Dog says woof!
}
在这个示例中, 当对 Dog 实例调用 printAnimalInfo() 函数时, 编译器将其向上转换为 Animal, 因为这是预期的参数类型. 由于实际对象仍然是 Dog 实例, 编译器动态地从 Dog 类中解析 makeSound() 函数, 打印 "Dog says woof!".