继承(Inheritance)和多态(Polymorphism)是面向对象编程的两个核心概念,它们使得代码更具可重用性、可扩展性和灵活性。Dart 语言完全支持这两种特性。
1. 继承
继承允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法。子类可以重用父类的代码,并可以添加新的属性和方法,或者重写(Override)父类的方法。
在 Dart 中,使用 extends 关键字来实现继承。一个类只能继承一个父类(单继承)。
// 父类
class Animal {
String name;
Animal(this.name);
void eat() {
print("$name is eating.");
}
void sleep() {
print("$name is sleeping.");
}
}
// 子类 Dog 继承自 Animal
class Dog extends Animal {
String breed;
Dog(String name, this.breed) : super(name); // 调用父类的构造函数
void bark() {
print("$name is barking.");
}
@override // 重写父类方法
void eat() {
print("$name (a $breed) is happily eating dog food.");
}
}
// 子类 Cat 继承自 Animal
class Cat extends Animal {
Cat(String name) : super(name);
void meow() {
print("$name is meowing.");
}
@override
void eat() {
print("$name (a cat) is gracefully eating fish.");
}
}
void main() {
var animal = Animal("Generic Animal");
animal.eat(); // 输出: Generic Animal is eating.
var dog = Dog("Buddy", "Golden Retriever");
dog.eat(); // 输出: Buddy (a Golden Retriever) is happily eating dog food.
dog.bark(); // 输出: Buddy is barking.
dog.sleep(); // 继承自 Animal
var cat = Cat("Whiskers");
cat.eat(); // 输出: Whiskers (a cat) is gracefully eating fish.
cat.meow(); // 输出: Whiskers is meowing.
}
关键点:
extends 关键字:用于声明继承关系。super 关键字:用于调用父类的构造函数或方法。@override 注解:用于标记重写父类的方法。这是一个可选的注解,但强烈建议使用,它可以帮助编译器检查是否正确重写了方法,避免拼写错误等问题。2. 多态
多态意味着一个对象可以呈现出多种形态。在面向对象编程中,多态通常体现在以下几个方面:
Dog 对象可以被赋值给 Animal 类型的变量。void main() {
// 向上转型:子类对象可以被当作父类对象来引用
Animal myPet1 = Dog("Max", "Labrador");
Animal myPet2 = Cat("Luna");
// 调用 eat() 方法,实际执行的是子类中重写的方法
myPet1.eat(); // 输出: Max (a Labrador) is happily eating dog food.
myPet2.eat(); // 输出: Luna (a cat) is gracefully eating fish.
// List<Animal> 存储不同类型的 Animal 子类对象
List<Animal> pets = [Dog("Rocky", "Bulldog"), Cat("Milo"), Animal("Parrot")];
for (var pet in pets) {
pet.eat(); // 多态性体现:根据实际对象类型调用不同的 eat() 实现
}
// 输出:
// Rocky (a Bulldog) is happily eating dog food.
// Milo (a cat) is gracefully eating fish.
// Parrot is eating.
}
多态性使得代码更加灵活和通用。我们可以编写处理父类类型的方法,而这些方法可以自动适应其所有子类,无需为每个子类编写单独的代码。
继承和多态是 Flutter 框架的核心。Flutter 中的所有 Widget 都继承自 Widget 类,而 StatelessWidget 和 StatefulWidget 又继承自 Widget。这种继承关系和多态性使得 Flutter 的 UI 构建变得非常强大和灵活。
案例:不同类型的卡片组件
我们将创建一个基础的 BaseCard 类,然后派生出 ImageCard 和 TextCard 两个子类,分别用于显示图片和纯文本内容。这个案例将演示继承和多态在 Flutter UI 组件设计中的应用。
import 'package:flutter/material.dart';
// 基础卡片类 (父类)
abstract class BaseCard extends StatelessWidget {
final String title;
const BaseCard({super.key, required this.title});
// 抽象方法,子类必须实现
Widget buildContent(BuildContext context);
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.all(16.0),
elevation: 4.0,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
buildContent(context), // 调用子类实现的具体内容构建方法
],
),
),
);
}
}
// 图片卡片类 (子类)
class ImageCard extends BaseCard {
final String imageUrl;
final String description;
const ImageCard({
super.key,
required super.title,
required this.imageUrl,
required this.description,
});
@override
Widget buildContent(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Image.network(
imageUrl,
height: 150,
width: double.infinity,
fit: BoxFit.cover,
),
const SizedBox(height: 10),
Text(
description,
style: const TextStyle(fontSize: 16),
),
],
);
}
}
// 文本卡片类 (子类)
class TextCard extends BaseCard {
final String content;
const TextCard({
super.key,
required super.title,
required this.content,
});
@override
Widget buildContent(BuildContext context) {
return Text(
content,
style: const TextStyle(fontSize: 16),
);
}
}
class InheritanceAndPolymorphismExampleScreen extends StatelessWidget {
const InheritanceAndPolymorphismExampleScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("继承与多态应用案例"),
),
body: ListView(
children: <Widget>[
// 使用 ImageCard
ImageCard(
title: "美丽的风景",
imageUrl: "https://picsum.photos/id/237/200/300", // 示例图片 URL
description: "这是一张美丽的风景图片,展示了大自然的鬼斧神工。",
),
// 使用 TextCard
TextCard(
title: "关于 Dart 语言",
content: "Dart 是一种客户端优化的编程语言,旨在为多平台应用开发提供高效、可预测的性能。它被设计用于构建移动、桌面、Web 和后端应用程序。",
),
// 也可以将不同类型的卡片存储在同一个列表中,体现多态性
// List<BaseCard> cards = [
// ImageCard(
// title: "另一张图片",
// imageUrl: "https://picsum.photos/id/238/200/300",
// description: "这是通过多态性展示的另一张图片卡片。",
// ),
// TextCard(
// title: "多态文本",
// content: "这段文本通过多态性展示。",
// ),
// ];
// ... 在 ListView 中遍历 cards
],
),
);
}
}
void main() {
runApp(const MaterialApp(home: InheritanceAndPolymorphismExampleScreen()));
}
案例分析:
abstract class BaseCard extends StatelessWidget:我们定义了一个抽象类 BaseCard,它继承自 Flutter 的 StatelessWidget。抽象类不能直接实例化,它定义了一个通用的结构和行为,并强制子类实现某些方法(通过 abstract 关键字)。Widget buildContent(BuildContext context);:BaseCard 中定义了一个抽象方法 buildContent。这意味着任何继承 BaseCard 的子类都必须提供 buildContent 方法的具体实现。这体现了多态性,因为不同的子类会以自己的方式构建内容。ImageCard extends BaseCard 和 TextCard extends BaseCard:ImageCard 和 TextCard 分别继承自 BaseCard。它们都重写了 buildContent 方法,提供了各自特定的内容布局(图片和文本)。super.title:在子类的构造函数中,super.title 用于将 title 参数传递给父类 BaseCard 的构造函数。这是调用父类构造函数的方式。buildContent(context):在 BaseCard 的 build 方法中,我们调用了 buildContent(context)。由于多态性,当 BaseCard 的实例实际上是 ImageCard 或 TextCard 时,会调用相应子类中重写的 buildContent 方法,从而显示不同的内容。ListView 中的组合:在 InheritanceAndPolymorphismExampleScreen 中,我们直接在 ListView 的 children 中使用了 ImageCard 和 TextCard 的实例。尽管它们是不同的类,但由于它们都继承自 BaseCard(最终都继承自 Widget),它们可以被统一处理和渲染。这个案例清晰地展示了继承和多态在 Flutter UI 组件设计中的强大作用。通过继承,我们可以创建可复用的基础组件,并通过多态性实现组件行为的定制化,从而构建出灵活且易于维护的 UI 结构。Flutter 框架本身就是这种设计模式的典范。