Dart中sealed

2,725 阅读6分钟

sealed基础使用

在Dart中,使用sealed关键字可以创建封闭类(sealed class)。封闭类只能在同一个库文件中被继承。例如:

dart
sealed class Animal {
  void makeNoise() => print('Unknown animal noise!');
}

class Dog extends Animal {
  void makeNoise() => print('Bark!'); 
}

class Cat extends Animal {
  void makeNoise() => print('Meow!'); 
}

这里,Animal是一个封闭类(sealed class)。只有在同一个文件中,Dog和Cat类才能继承它。如果我们在其他文件中尝试继承Animal,会报错:

dart
class Fox extends Animal {   // Error: Cannot extend sealed class 'Animal'
} 

封闭类的主要目的有:

  1. 限制继承范围。只有在同一个库中我们才能继承该类,这使得该类的子类型数量是可知的,更易于管理。
  2. 实现完备性检查。因为我们知道所有的子类,所以可以在父类中为每个子类实现相应的方法和属性,并在编译时检查是否完成全部实现。这可以提高代码健壮性。
  3. 方便语句匹配。因为子类数量是确定的,我们可以在父类中使用switch语句根据子类类型执行相应逻辑,这在其他语言中不太方便。例如:
dart
void makeAnimalNoise(Animal animal) {
  switch (animal.runtimeType) {
    case Dog: 
      animal.makeNoise(); 
      break;
    case Cat:
      animal.makeNoise();
      break;
  } 
}

 这里,因为Animal的子类只有Dog和Cat,所以我们可以使用switch根据子类型执行相应方法。总之,封闭类是Dart中一种限制继承与实现完备性检查的语言结构。熟练掌握它有助于我们开发出更加健壮的Dart程序。所以封闭类的特性和用法也值得我们在学习Dart的过程中进行深入理解与实践。每次定义一个继承体系时,我们也可以考虑是否适合使用封闭类,并实践一下。这无疑可以加深我们对其的理解,也可以锻炼我们在设计API和类结构上的能力。任何技术,都需要理论与实践相结合,才能运用自如。Dart的各种语言结构和特性也不例外,需要我们通过学习与实践来熟练掌握。

封闭类(sealed class)是隐式抽象的,不能被直接实例化。

例如,如果我们定义一个封闭类:

dart
sealed class Animal {}

然后尝试实例化它:

dart
var a = Animal();  // Error: Cannot instantiate abstract class 'Animal'

会报错,不能实例化抽象类Animal。这是因为封闭类隐式地被视为抽象类。尽管我们没有使用abstract关键字,但是Dart会自动将其视为抽象类,因为:1. 它不能被外部继承,只能在同一库中继承
2. 其子类型是已知且固定的所以,封闭类本质上是一种抽象类,只是语法上看似普通类。这使得它具有抽象类的一些特点:1. 不能被实例化,必须由子类实例化
2. 可以有抽象方法,要求子类实现
3. 可以实现完备性检查,确保子类实现了所有必要方法例如:

dart
sealed abstract class Animal {
  void makeNoise();  // 抽象方法
}

class Dog extends Animal {
  void makeNoise() => print('Bark!');
}

class Cat extends Animal {
  void makeNoise() => print('Meow!');
}

这里,Animal是一个封闭抽象类,不能被实例化。它有一个抽象方法makeNoise(),要求子类Dog和Cat实现。这样可以确保所有子类都实现了该方法。所以,封闭类具有抽象类的这些特点,可以看作是一种隐式抽象类。由于它限定了子类型,所以在设计类继承体系时,使用封闭类可以实现更严密的完备性检查。这也是它的主要优点之一。理解封闭类的这一本质,可以让我们在Dart开发中更加灵活和高效地应用它。每次定义一个继承关系时,我们就可以考虑是否使用封闭类,并思考如何充分利用它的这一特点。这也是我们熟练掌握Dart语言的一个方面。所以,总结一下,封闭类有以下特征:- 隐式抽象,不能实例化

  • 可以有抽象方法
  • 可以实现完备性检查
  • 子类型是确定的希望通过这些总结,可以让大家对Dart封闭类有一个更深入的理解。要真正掌握它,还是需要在实践中不断运用与体会。这也是我们学习Dart与提高技能的过程中必不可少的一步。理论与实践,两者缺一不可。封闭类的学习也同样需要我们按这个法则来进行。

封闭类(sealed class)在Dart中还有一些其他用法和语法细节:

  1. 可以继承Object类:
dart
sealed class Animal extends Object {
  // ...
}

封闭类可以继承Object类,因为Object是Dart中所有类的父类。2. 可以实现接口:

dart
sealed class Animal implements NoiseMaker {
  void makeNoise() => ...
}

封闭类可以实现接口,这在需要让子类实现某些方法时很有用。3. 可以有抽象方法:

dart
abstract sealed class Animal {
  void makeNoise();  
}

 封闭类可以是抽象类,要求子类实现某些抽象方法。这可以实现完备性检查,确保所有子类都实现了所需方法。

  1. 子类可以在任何文件中:尽管只能在同一个库中继承封闭类,但是其子类可以定义在任意文件中。例如:animal.dart:
dart
sealed class Animal {} 

dog.dart:

dart
class Dog extends Animal {} 

cat.dart:

dart 
class Cat extends Animal {}

这里Dog和Cat类在不同文件中,但是因为在同一个库中,所以可以继承Animal类。5. 可以扩展已有类:我们可以在已有类上添加sealed关键字,使其成为封闭类。例如:

dart
class Animal {
  ...
}

sealed class Animal extends Object {
  ...
}

现在Animal成为一个封闭类,只允许在同一库中继承。原来的Animal子类依然有效。所以,总结一下封闭类的其他细节:

  • 可以继承Object类和实现接口
  • 可以是抽象类
  • 子类可以在任意文件中,只要在同一库
  • 可以通过扩展已有类使其成为封闭类

这些特性使得封闭类在Dart中更加灵活使用。要真正掌握它,仍然需要我们在学习与实践中不断体会与总结。

每次使用封闭类,我们可以尝试不同的方式,如继承Object类,实现接口,在不同文件中定义子类等,来加深对其的理解。这也是我们学习Dart与成长为Dart高手的过程中必不可少的一部分。

理论和实践相结合,这是我们学习任何技能的基本法则。Dart的各种语言结构也需要我们用这种方式去理解与熟练掌握。封闭类作为Dart的一项重要特性,自然也不例外。