Menu
CoddyTech

is 和 as 运算符

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 60 课,共 110 课。

虽然 runtimeType 会告诉你确切的类型,但 Dart 提供了两个更实用的运算符,用于类型检查和类型转换:is 和 as。

is 运算符用于检查对象是否属于特定类型,并返回一个布尔值。与 runtimeType 不同,对于父类型,它也会返回 true:

class Animal {}
class Dog extends Animal {}

void main() {
  Animal pet = Dog();
  
  print(pet is Dog);     // true
  print(pet is Animal);  // true(Dog 是一个 Animal)
  print(pet is String);  // false
}

在 if 语句中使用 is 时,Dart 会自动进行类型提升,让你无需显式类型转换即可访问子类成员:

void handleAnimal(Animal animal) {
  if (animal is Dog) {
    // 在这里,Dart 知道 animal 是 Dog 类型
    animal.bark();  // 可以调用 Dog 特有的方法
  }
}

as 运算符会将对象显式转换为特定类型。当你确定对象的类型时,可以使用它:

Animal pet = Dog();
Dog myDog = pet as Dog;  // 转换为 Dog 类型
myDog.bark();

使用 as 时要小心,如果类型转换失败,就会抛出异常。因此,与其直接使用 as,通常结合 is 和类型提升会更安全。你也可以使用 is! 来检查对象是否不是某种类型。

challenge icon

挑战

简单

我们来构建一个形状处理系统,使用 is 和 as 运算符来识别和处理不同类型的形状。你将创建一个形状层次结构,并编写函数来检查类型和安全地访问特定类型的属性。

你将把代码分成两个文件:

  • shapes.dart:在这里定义形状层次结构:
    • 创建一个 Shape 类,包含 String name 属性和构造函数。添加一个 describe() 方法,用来打印 [name] is a shape
    • 创建一个继承自 Shape 的 Circle 类,并添加 double radius 属性。添加一个 getCircleInfo() 方法,用来打印 Circle with radius: [radius]
    • 创建一个继承自 Shape 的 Rectangle 类,并添加 double width 和 double height 属性。添加一个 getRectangleInfo() 方法,用来打印 Rectangle: [width] x [height]
  • main.dart:导入形状文件,并创建一个 processShape(Shape shape) 函数,该函数需要:
    • 首先对形状调用 describe()
    • 使用 is 检查形状是否为 Circle。如果是,则使用类型提升调用 getCircleInfo()
    • 使用 is 检查形状是否为 Rectangle。如果是,则使用 as 运算符进行类型转换并调用 getRectangleInfo()
    • 使用 is! 检查形状是否既不是 Circle,也不是 Rectangle。如果是,则打印 Unknown shape type
    然后,在你的 main() 函数中:
    • 创建一个名为 'Round'、半径为 5.0 的 Circle,并将它传给 processShape()
    • 打印一个空行
    • 创建一个名为 'Box'、宽度为 4.0、高度为 3.0 的 Rectangle,并将它传给 processShape()
    • 打印一个空行
    • 创建一个名为 'Mystery' 的基础 Shape,并将它传给 processShape()

这个挑战展示了两种方法:对 Circle 使用 is 和自动类型提升,以及对 Rectangle 使用 as 进行显式类型转换。你还将看到 is! 如何帮助识别不属于任何特定子类型的形状。

预期输出:

Round is a shape
Circle with radius: 5.0

Box is a shape
Rectangle: 4.0 x 3.0

Mystery is a shape
Unknown shape type

亲手试试

import 'shapes.dart';

// TODO:创建函数 processShape(Shape shape),使其:
// 1. 首先调用该形状的 describe()
// 2. 用 'is' 检查 shape 是否为 Circle;如果是,就通过类型提升调用 getCircleInfo()
// 3. 用 'is' 检查 shape 是否为 Rectangle;如果是,就用 'as' 运算符进行类型转换并调用 getRectangleInfo()
// 4. 用 'is!' 检查 shape 既不是 Circle 也不是 Rectangle;如果是,就打印 "Unknown shape type"

void main() {
  // TODO:创建一个名为 'Round'、半径为 5.0 的 Circle,并将其传给 processShape()
  
  // TODO:打印一个空行
  
  // TODO:创建一个名为 'Box'、宽为 4.0、高为 3.0 的 Rectangle,并将其传给 processShape()
  
  // TODO:打印一个空行
  
  // TODO:创建一个名为 'Mystery' 的基础 Shape,并将其传给 processShape()
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器