Dart Class API 详细总结
基于Dart官方API文档与实践经验整理
目录
概述
在Dart中,class
是面向对象编程的核心概念。Dart是一门纯面向对象的语言,所有的值都是对象,所有的对象都是类的实例。
核心特性
- 单继承:每个类只能有一个父类
- 接口实现:可以实现多个接口
- 混入支持:通过mixin实现代码复用
- 构造函数多样性:支持多种构造函数形式
- 访问控制:通过下划线实现私有成员
- 泛型支持:支持泛型类和方法
- 操作符重载:可以重载运算符
类的定义与基础语法
1. 基本类定义
dart
// 最简单的类定义
class Person {
// 类体
}
// 带属性和方法的类
class Student {
// 实例变量
String name;
int age;
// 构造函数
Student(this.name, this.age);
// 方法
void introduce() {
print('我是$name,今年$age岁');
}
}
2. 访问控制
dart
class BankAccount {
// 公开属性
String accountNumber;
// 私有属性(以下划线开头)
double _balance;
BankAccount(this.accountNumber, this._balance);
// 公开方法
double get balance => _balance;
// 私有方法
void _validateAmount(double amount) {
if (amount <= 0) {
throw ArgumentError('金额必须大于0');
}
}
// 公开方法调用私有方法
void deposit(double amount) {
_validateAmount(amount);
_balance += amount;
}
}
3. 静态成员
dart
class MathUtils {
// 静态常量
static const double pi = 3.14159;
// 静态变量
static int calculationCount = 0;
// 静态方法
static double circleArea(double radius) {
calculationCount++;
return pi * radius * radius;
}
// 静态getter
static String get info => '已计算$calculationCount次';
}
// 使用静态成员
void main() {
print(MathUtils.pi); // 3.14159
print(MathUtils.circleArea(5)); // 78.53975
print(MathUtils.info); // 已计算1次
}
构造函数详解
1. 默认构造函数
dart
class Point {
double x;
double y;
// 默认构造函数
Point(this.x, this.y);
}
// 使用
Point p = Point(3.0, 4.0);
2. 命名构造函数
dart
class Rectangle {
double width;
double height;
// 默认构造函数
Rectangle(this.width, this.height);
// 命名构造函数:创建正方形
Rectangle.square(double side) : width = side, height = side;
// 命名构造函数:从另一个Rectangle创建
Rectangle.copy(Rectangle other) : width = other.width, height = other.height;
// 命名构造函数:创建单位矩形
Rectangle.unit() : width = 1.0, height = 1.0;
}
// 使用命名构造函数
Rectangle rect1 = Rectangle(10, 20);
Rectangle square = Rectangle.square(15);
Rectangle copy = Rectangle.copy(rect1);
Rectangle unit = Rectangle.unit();
3. 工厂构造函数
dart
class Logger {
final String name;
static final Map<String, Logger> _cache = <String, Logger>{};
// 私有构造函数
Logger._internal(this.name);
// 工厂构造函数 - 实现单例模式
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
void log(String message) {
print('[$name] $message');
}
}
// 工厂构造函数的高级用法
abstract class Shape {
factory Shape(String type) {
switch (type) {
case 'circle':
return Circle();
case 'rectangle':
return Rectangle.unit();
default:
throw ArgumentError('未知的形状类型: $type');
}
}
double get area;
}
class Circle implements Shape {
double radius = 1.0;
@override
double get area => 3.14159 * radius * radius;
}
4. 重定向构造函数
dart
class Person {
String name;
int age;
String email;
// 主构造函数
Person(this.name, this.age, this.email);
// 重定向构造函数
Person.withNameAndAge(String name, int age) : this(name, age, '');
// 重定向到命名构造函数
Person.child(String name) : this.withNameAndAge(name, 0);
}
5. 初始化列表
在Dart语言中,初始化列表(initializer list)通常用于初始化类的实例变量,特别是在构造函数中。初始化列表允许你在对象被完全构造之前,先对某些实例变量进行初始化。这对于执行一些需要在构造函数体之前完成的初始化操作非常有用,比如调用一些需要前置条件的函数或方法。
dart
class Circle {
final double radius;
final double area;
final double circumference;
// 使用初始化列表计算derived properties
Circle(double radius)
: this.radius = radius,
area = 3.14159 * radius * radius,
circumference = 2 * 3.14159 * radius {
// 构造函数体(可选)
print('创建了半径为$radius的圆');
}
// 断言初始化
Circle.withValidation(double radius)
: assert(radius > 0, '半径必须大于0'),
this.radius = radius,
area = 3.14159 * radius * radius,
circumference = 2 * 3.14159 * radius;
}
6. 常量构造函数
dart
class ImmutablePoint {
final double x;
final double y;
// 常量构造函数
const ImmutablePoint(this.x, this.y);
// 命名常量构造函数
const ImmutablePoint.origin() : x = 0, y = 0;
}
// 使用常量构造函数
const point1 = ImmutablePoint(3, 4);
const point2 = ImmutablePoint.origin();
// 编译时常量
const points = [
ImmutablePoint(0, 0),
ImmutablePoint(1, 1),
ImmutablePoint(2, 2),
];
属性与方法
1. 属性定义
dart
class Product {
// 实例变量
String name;
double _price; // 私有变量
// 自动生成getter和setter
String? description;
// 只读属性
final String id;
// 延迟初始化
late String category;
Product(this.name, this._price, this.id);
// 自定义getter
double get price => _price;
// 自定义setter
set price(double value) {
if (value < 0) {
throw ArgumentError('价格不能为负数');
}
_price = value;
}
// 计算属性
double get priceWithTax => _price * 1.1;
// 只读计算属性
String get displayName => '$name (¥${_price.toStringAsFixed(2)})';
}
2. 方法定义
dart
class Calculator {
// 实例方法
double add(double a, double b) {
return a + b;
}
// 可选参数方法
double multiply(double a, [double b = 1.0]) {
return a * b;
}
// 命名参数方法
double calculate({
required double a,
required double b,
required String operation,
}) {
switch (operation) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
if (b == 0) throw ArgumentError('除数不能为0');
return a / b;
default:
throw ArgumentError('不支持的操作: $operation');
}
}
// 静态方法
static double percentage(double value, double percent) {
return value * (percent / 100);
}
}
3. Getter和Setter
dart
class Temperature {
double _celsius = 0;
// Getter
double get celsius => _celsius;
double get fahrenheit => _celsius * 9 / 5 + 32;
double get kelvin => _celsius + 273.15;
// Setter
set celsius(double value) {
if (value < -273.15) {
throw ArgumentError('温度不能低于绝对零度');
}
_celsius = value;
}
set fahrenheit(double value) {
celsius = (value - 32) * 5 / 9;
}
set kelvin(double value) {
celsius = value - 273.15;
}
}
// 使用
Temperature temp = Temperature();
temp.celsius = 25;
print('${temp.celsius}°C = ${temp.fahrenheit}°F = ${temp.kelvin}K');
继承与多态
1. 基本继承
dart
// 父类
class Animal {
String name;
int age;
Animal(this.name, this.age);
void eat() {
print('$name正在吃东西');
}
void sleep() {
print('$name正在睡觉');
}
// 虚方法,可以被子类重写
void makeSound() {
print('$name发出声音');
}
}
// 子类
class Dog extends Animal {
String breed;
// 调用父类构造函数
Dog(String name, int age, this.breed) : super(name, age);
// 重写父类方法
@override
void makeSound() {
print('$name汪汪叫');
}
// 子类特有方法
void wagTail() {
print('$name摇尾巴');
}
}
class Cat extends Animal {
bool isIndoor;
Cat(String name, int age, this.isIndoor) : super(name, age);
@override
void makeSound() {
print('$name喵喵叫');
}
void climb() {
print('$name在爬树');
}
}
2. 多态性
dart
void demonstratePolymorphism() {
List<Animal> animals = [
Dog('旺财', 3, '金毛'),
Cat('咪咪', 2, true),
Dog('大黄', 5, '土狗'),
];
// 多态:同样的调用,不同的行为
for (Animal animal in animals) {
animal.makeSound(); // 根据实际类型调用相应的方法
}
// 类型检查和转换
for (Animal animal in animals) {
if (animal is Dog) {
animal.wagTail(); // 安全转换
} else if (animal is Cat) {
animal.climb();
}
}
}
3. 抽象方法和super调用
dart
abstract class Vehicle {
String brand;
int year;
Vehicle(this.brand, this.year);
// 抽象方法,必须由子类实现
void start();
void stop();
// 具体方法,可以被子类使用
void displayInfo() {
print('$brand ($year年)');
}
}
class Car extends Vehicle {
int doors;
Car(String brand, int year, this.doors) : super(brand, year);
@override
void start() {
print('汽车发动引擎');
}
@override
void stop() {
print('汽车停止引擎');
}
@override
void displayInfo() {
super.displayInfo(); // 调用父类方法
print('门数: $doors');
}
}
抽象类与接口
1. 抽象类
dart
abstract class Shape {
// 抽象属性(通过getter定义)
double get area;
double get perimeter;
// 抽象方法
void draw();
// 具体方法
void printInfo() {
print('面积: $area, 周长: $perimeter');
}
// 工厂构造函数
factory Shape.create(String type, List<double> params) {
switch (type) {
case 'circle':
return Circle(params[0]);
case 'rectangle':
return Rectangle(params[0], params[1]);
default:
throw ArgumentError('不支持的形状类型');
}
}
}
class Circle extends Shape {
final double radius;
Circle(this.radius);
@override
double get area => 3.14159 * radius * radius;
@override
double get perimeter => 2 * 3.14159 * radius;
@override
void draw() {
print('绘制半径为$radius的圆');
}
}
2. 接口实现
dart
// 隐式接口:任何类都可以作为接口
class Flyable {
void fly() {
print('飞行中...');
}
}
class Swimmable {
void swim() {
print('游泳中...');
}
}
// 实现多个接口
class Duck implements Flyable, Swimmable {
@override
void fly() {
print('鸭子在飞');
}
@override
void swim() {
print('鸭子在游泳');
}
}
// 同时继承和实现
class Robot extends Machine implements Flyable, Swimmable {
Robot(String model) : super(model);
@override
void fly() {
print('机器人启动飞行模式');
}
@override
void swim() {
print('机器人启动游泳模式');
}
}
class Machine {
String model;
Machine(this.model);
void operate() {
print('$model正在运行');
}
}
混入(Mixin)
1. 基本Mixin
dart
// 定义mixin
mixin Flyable {
void fly() {
print('正在飞行');
}
void land() {
print('正在降落');
}
}
mixin Swimmable {
void swim() {
print('正在游泳');
}
void dive() {
print('正在潜水');
}
}
// 使用mixin
class Bird with Flyable {
String name;
Bird(this.name);
void chirp() {
print('$name在叫');
}
}
class Fish with Swimmable {
String species;
Fish(this.species);
}
class Duck extends Bird with Swimmable {
Duck(String name) : super(name);
@override
void fly() {
print('$name鸭子在飞');
}
}
2. 带约束的Mixin
dart
class Animal {
String name;
Animal(this.name);
}
// mixin只能被Animal的子类使用
mixin Walker on Animal {
void walk() {
print('$name正在走路');
}
void run() {
print('$name正在跑步');
}
}
class Dog extends Animal with Walker {
Dog(String name) : super(name);
}
class Cat extends Animal with Walker {
Cat(String name) : super(name);
@override
void walk() {
print('$name优雅地走着');
}
}
3. Mixin的高级用法
dart
mixin Serializable {
Map<String, dynamic> toJson();
void fromJson(Map<String, dynamic> json);
String serialize() {
return toJson().toString();
}
}
mixin Cacheable {
static final Map<String, dynamic> _cache = {};
String get cacheKey;
void cache() {
_cache[cacheKey] = this;
}
static T? getCached<T>(String key) {
return _cache[key] as T?;
}
}
class User with Serializable, Cacheable {
String name;
String email;
int age;
User(this.name, this.email, this.age);
@override
String get cacheKey => 'user_$email';
@override
Map<String, dynamic> toJson() {
return {
'name': name,
'email': email,
'age': age,
};
}
@override
void fromJson(Map<String, dynamic> json) {
name = json['name'];
email = json['email'];
age = json['age'];
}
}
枚举类
1. 基本枚举
dart
// 简单枚举
enum Color {
red,
green,
blue,
yellow,
}
// 使用枚举
void useBasicEnum() {
Color favorite = Color.blue;
print(favorite); // Color.blue
print(favorite.name); // blue
print(favorite.index); // 2
// 遍历所有枚举值
for (Color color in Color.values) {
print('${color.name}: ${color.index}');
}
// switch语句
switch (favorite) {
case Color.red:
print('红色');
break;
case Color.green:
print('绿色');
break;
case Color.blue:
print('蓝色');
break;
case Color.yellow:
print('黄色');
break;
}
}
2. 增强枚举(Dart 2.17+)
dart
enum Planet {
mercury(3.303e+23, 2.4397e6),
venus(4.869e+24, 6.0518e6),
earth(5.976e+24, 6.37814e6),
mars(6.421e+23, 3.3972e6);
// 枚举构造函数
const Planet(this.mass, this.radius);
// 实例变量
final double mass; // 质量 (kg)
final double radius; // 半径 (m)
// 计算属性
double get surfaceGravity => 6.67300E-11 * mass / (radius * radius);
// 实例方法
double surfaceWeight(double mass) => mass * surfaceGravity;
// 静态方法
static Planet? findByName(String name) {
for (Planet planet in Planet.values) {
if (planet.name == name) return planet;
}
return null;
}
@override
String toString() => '${name}: 质量=$mass kg, 半径=$radius m';
}
// 使用增强枚举
void useEnhancedEnum() {
Planet earth = Planet.earth;
print(earth.surfaceGravity); // 9.802652743337129
print(earth.surfaceWeight(70)); // 686.1856920358991
Planet? mars = Planet.findByName('mars');
print(mars?.toString());
}
3. 实现接口的枚举
dart
abstract class Comparable<T> {
int compareTo(T other);
}
enum Status implements Comparable<Status> {
pending(0, '待处理'),
processing(1, '处理中'),
completed(2, '已完成'),
cancelled(-1, '已取消');
const Status(this.priority, this.description);
final int priority;
final String description;
@override
int compareTo(Status other) => priority.compareTo(other.priority);
bool get isActive => this != Status.cancelled;
Status? get nextStatus {
switch (this) {
case Status.pending:
return Status.processing;
case Status.processing:
return Status.completed;
default:
return null;
}
}
}
扩展方法
1. 基本扩展方法
dart
// 为String添加扩展方法
extension StringExtensions on String {
// 判断是否为邮箱
bool get isEmail {
return RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(this);
}
// 首字母大写
String get capitalize {
if (isEmpty) return this;
return '${this[0].toUpperCase()}${substring(1).toLowerCase()}';
}
// 反转字符串
String get reverse {
return split('').reversed.join();
}
// 移除所有空白字符
String get removeAllWhitespace {
return replaceAll(RegExp(r'\s+'), '');
}
}
// 为int添加扩展方法
extension IntExtensions on int {
// 判断是否为偶数
bool get isEven => this % 2 == 0;
// 判断是否为奇数
bool get isOdd => this % 2 != 0;
// 阶乘
int get factorial {
if (this < 0) throw ArgumentError('负数没有阶乘');
if (this <= 1) return 1;
return this * (this - 1).factorial;
}
// 转换为罗马数字
String get toRoman {
if (this <= 0 || this > 3999) {
throw ArgumentError('只支持1-3999的数字');
}
const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
const symbols = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
String result = '';
int num = this;
for (int i = 0; i < values.length; i++) {
while (num >= values[i]) {
result += symbols[i];
num -= values[i];
}
}
return result;
}
}
// 使用扩展方法
void useExtensions() {
String email = 'user@example.com';
print(email.isEmail); // true
print('hello world'.capitalize); // Hello world
print('dart'.reverse); // trad
int number = 5;
print(number.isEven); // false
print(number.factorial); // 120
print(number.toRoman); // V
}
2. 泛型扩展
dart
// 为List添加扩展方法
extension ListExtensions<T> on List<T> {
// 安全获取元素
T? getOrNull(int index) {
if (index < 0 || index >= length) return null;
return this[index];
}
// 分组
Map<K, List<T>> groupBy<K>(K Function(T) keySelector) {
Map<K, List<T>> map = {};
for (T element in this) {
K key = keySelector(element);
map.putIfAbsent(key, () => []).add(element);
}
return map;
}
// 去重
List<T> get distinct {
return toSet().toList();
}
// 分批处理
List<List<T>> chunk(int size) {
List<List<T>> chunks = [];
for (int i = 0; i < length; i += size) {
chunks.add(sublist(i, (i + size > length) ? length : i + size));
}
return chunks;
}
}
// 为Map添加扩展方法
extension MapExtensions<K, V> on Map<K, V> {
// 安全获取值
V? getOrNull(K key) => this[key];
// 获取值或默认值
V getOrDefault(K key, V defaultValue) => this[key] ?? defaultValue;
// 反转键值
Map<V, K> get inverse {
return map((key, value) => MapEntry(value, key));
}
}
3. 条件扩展
dart
// 只为特定类型添加扩展
extension NumericStringExtensions on String {
// 只有数字字符串才能转换
int? get toIntOrNull {
return int.tryParse(this);
}
double? get toDoubleOrNull {
return double.tryParse(this);
}
}
// 为可空类型添加扩展
extension NullableExtensions<T> on T? {
// 如果不为null则执行操作
R? let<R>(R Function(T) operation) {
if (this != null) {
return operation(this!);
}
return null;
}
// 如果为null则返回默认值
T orElse(T defaultValue) {
return this ?? defaultValue;
}
}
泛型类
1. 基本泛型类
dart
// 泛型类定义
class Box<T> {
T? _value;
// 泛型构造函数
Box([this._value]);
// 泛型方法
void put(T value) {
_value = value;
}
T? get() {
return _value;
}
bool get isEmpty => _value == null;
// 类型检查
bool isType<R>() => _value is R;
// 类型转换
R? as<R>() => _value as R?;
}
// 使用泛型类
void useGenericClass() {
Box<String> stringBox = Box<String>('Hello');
Box<int> intBox = Box<int>(42);
print(stringBox.get()); // Hello
print(intBox.get()); // 42
stringBox.put('World');
print(stringBox.get()); // World
}
2. 有界泛型
dart
// 泛型约束
class NumberBox<T extends num> {
T value;
NumberBox(this.value);
// 可以使用num的方法
T add(T other) => (value + other) as T;
bool get isPositive => value > 0;
String get formattedValue => value.toStringAsFixed(2);
}
// 多重约束
abstract class Serializable {
Map<String, dynamic> toJson();
}
class DataContainer<T extends Object & Serializable> {
T data;
DataContainer(this.data);
// 可以安全调用Object和Serializable的方法
Map<String, dynamic> serialize() {
return {
'type': data.runtimeType.toString(),
'data': data.toJson(),
};
}
}
3. 泛型方法
dart
class Utility {
// 泛型方法
static T? find<T>(List<T> list, bool Function(T) predicate) {
for (T item in list) {
if (predicate(item)) return item;
}
return null;
}
// 多个泛型参数
static Map<K, V> combine<K, V>(List<K> keys, List<V> values) {
Map<K, V> result = {};
int length = keys.length < values.length ? keys.length : values.length;
for (int i = 0; i < length; i++) {
result[keys[i]] = values[i];
}
return result;
}
// 泛型约束方法
static T max<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
}
操作符重载
1. 算术操作符
dart
class Vector2D {
final double x, y;
const Vector2D(this.x, this.y);
// 加法
Vector2D operator +(Vector2D other) {
return Vector2D(x + other.x, y + other.y);
}
// 减法
Vector2D operator -(Vector2D other) {
return Vector2D(x - other.x, y - other.y);
}
// 乘法(标量)
Vector2D operator *(double scalar) {
return Vector2D(x * scalar, y * scalar);
}
// 除法
Vector2D operator /(double scalar) {
if (scalar == 0) throw ArgumentError('除数不能为0');
return Vector2D(x / scalar, y / scalar);
}
// 一元负号
Vector2D operator -() {
return Vector2D(-x, -y);
}
@override
String toString() => 'Vector2D($x, $y)';
}
2. 比较操作符
dart
class Money implements Comparable<Money> {
final double amount;
final String currency;
const Money(this.amount, this.currency);
// 相等操作符
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is Money &&
runtimeType == other.runtimeType &&
amount == other.amount &&
currency == other.currency;
}
@override
int get hashCode => Object.hash(amount, currency);
// 比较操作符
@override
int compareTo(Money other) {
if (currency != other.currency) {
throw ArgumentError('不能比较不同货币');
}
return amount.compareTo(other.amount);
}
bool operator <(Money other) => compareTo(other) < 0;
bool operator <=(Money other) => compareTo(other) <= 0;
bool operator >(Money other) => compareTo(other) > 0;
bool operator >=(Money other) => compareTo(other) >= 0;
@override
String toString() => '$amount $currency';
}
3. 集合操作符
dart
class CustomList<T> {
final List<T> _items = [];
// 索引操作符
T operator [](int index) => _items[index];
void operator []=(int index, T value) {
_items[index] = value;
}
// 添加操作符
CustomList<T> operator +(CustomList<T> other) {
CustomList<T> result = CustomList<T>();
result._items.addAll(_items);
result._items.addAll(other._items);
return result;
}
// 包含操作符(需要定义contains方法)
bool contains(T element) => _items.contains(element);
void add(T item) => _items.add(item);
int get length => _items.length;
@override
String toString() => _items.toString();
}
元数据注解
1. 内置注解
dart
class Example {
// 过时注解
@deprecated
void oldMethod() {
print('这个方法已过时');
}
@Deprecated('使用newMethod()替代')
void anotherOldMethod() {
print('另一个过时的方法');
}
// 重写注解
@override
String toString() {
return 'Example instance';
}
// 必需注解(需要meta包)
void processData({
required String data,
@required String? optionalData, // 旧式写法
}) {
// 处理数据
}
}
2. 自定义注解
dart
// 定义自定义注解
class ApiEndpoint {
final String path;
final String method;
const ApiEndpoint(this.path, {this.method = 'GET'});
}
class Cacheable {
final Duration duration;
const Cacheable({this.duration = const Duration(minutes: 5)});
}
// 使用自定义注解
class UserController {
@ApiEndpoint('/users', method: 'GET')
@Cacheable(duration: Duration(minutes: 10))
List<User> getUsers() {
// 获取用户列表
return [];
}
@ApiEndpoint('/users', method: 'POST')
User createUser(User user) {
// 创建用户
return user;
}
}
3. 反射和注解处理
dart
import 'dart:mirrors';
// 注解处理工具类
class AnnotationProcessor {
static void processClass(Type type) {
ClassMirror classMirror = reflectClass(type);
// 处理类级别的注解
for (InstanceMirror annotation in classMirror.metadata) {
print('类注解: ${annotation.reflectee}');
}
// 处理方法注解
classMirror.declarations.forEach((symbol, declaration) {
if (declaration is MethodMirror) {
for (InstanceMirror annotation in declaration.metadata) {
print('方法${MirrorSystem.getName(symbol)}的注解: ${annotation.reflectee}');
}
}
});
}
}
性能考虑
1. 构造函数性能
dart
// ❌ 性能较差的构造函数
class SlowPerson {
String name;
String email;
DateTime createdAt;
SlowPerson(this.name, this.email) : createdAt = DateTime.now() {
// 构造函数体中的重计算
name = name.trim().toLowerCase();
email = email.trim().toLowerCase();
// 验证逻辑
if (!email.contains('@')) {
throw ArgumentError('无效的邮箱地址');
}
}
}
// ✅ 性能优化的构造函数
class FastPerson {
final String name;
final String email;
final DateTime createdAt;
// 使用工厂构造函数进行预处理
factory FastPerson(String name, String email) {
String cleanName = name.trim().toLowerCase();
String cleanEmail = email.trim().toLowerCase();
if (!cleanEmail.contains('@')) {
throw ArgumentError('无效的邮箱地址');
}
return FastPerson._internal(cleanName, cleanEmail, DateTime.now());
}
// 私有构造函数,直接赋值
FastPerson._internal(this.name, this.email, this.createdAt);
}
2. 继承链优化
dart
// ❌ 过深的继承链
class A {
void methodA() {}
}
class B extends A {
void methodB() {}
}
class C extends B {
void methodC() {}
}
class D extends C {
void methodD() {}
}
// ✅ 使用组合和mixin
mixin FeatureA {
void methodA() {}
}
mixin FeatureB {
void methodB() {}
}
mixin FeatureC {
void methodC() {}
}
class OptimizedClass with FeatureA, FeatureB, FeatureC {
void methodD() {}
}
3. 内存优化
dart
// 对象池模式
class ObjectPool<T> {
final List<T> _pool = [];
final T Function() _factory;
ObjectPool(this._factory);
T acquire() {
if (_pool.isNotEmpty) {
return _pool.removeLast();
}
return _factory();
}
void release(T object) {
if (_pool.length < 100) { // 限制池大小
_pool.add(object);
}
}
}
// 使用对象池
class ExpensiveObject {
late List<int> data;
ExpensiveObject() {
reset();
}
void reset() {
data = List.filled(1000, 0);
}
}
final ObjectPool<ExpensiveObject> pool =
ObjectPool(() => ExpensiveObject());
void useObjectPool() {
ExpensiveObject obj = pool.acquire();
// 使用对象
obj.reset(); // 重置状态
pool.release(obj); // 归还到池中
}
常见陷阱和错误
1. 构造函数陷阱
dart
class BadExample {
String name;
int age;
// ❌ 错误:尝试在初始化列表中使用this
// BadExample(String n, int a) : name = this.processName(n), age = a;
// ❌ 错误:final字段必须在构造函数完成前初始化
final String id = generateId(); // 这可能不是你想要的
BadExample(this.name, this.age);
String processName(String name) => name.trim();
static String generateId() => DateTime.now().millisecondsSinceEpoch.toString();
}
// ✅ 正确的方式
class GoodExample {
final String name;
final int age;
final String id;
GoodExample(String rawName, this.age)
: name = rawName.trim(),
id = DateTime.now().millisecondsSinceEpoch.toString();
// 或使用工厂构造函数
factory GoodExample.create(String rawName, int age) {
return GoodExample(rawName.trim(), age);
}
}
2. 继承和重写陷阱
dart
class Parent {
void method() {
print('Parent method');
}
// ❌ 私有方法不能被重写
void _privateMethod() {
print('Private method');
}
}
class Child extends Parent {
// ❌ 这不是重写,而是创建了新方法
void _privateMethod() {
print('Child private method');
}
// ✅ 正确的重写
@override
void method() {
super.method(); // 可选:调用父类方法
print('Child method');
}
}
3. 混入顺序陷阱
dart
mixin A {
void method() => print('A');
}
mixin B {
void method() => print('B');
}
mixin C {
void method() => print('C');
}
// 混入顺序很重要
class Example1 with A, B, C {} // method()输出: C
class Example2 with C, B, A {} // method()输出: A
class Example3 with A, C, B {} // method()输出: B
void testMixinOrder() {
Example1().method(); // C
Example2().method(); // A
Example3().method(); // B
}
最佳实践
1. 类设计原则
dart
// ✅ 单一职责原则
class User {
final String id;
final String name;
final String email;
const User({required this.id, required this.name, required this.email});
// 只负责用户数据
}
class UserValidator {
static bool isValidEmail(String email) {
return RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(email);
}
static bool isValidName(String name) {
return name.trim().isNotEmpty && name.length >= 2;
}
}
class UserRepository {
Future<User> save(User user) async {
// 保存用户逻辑
return user;
}
Future<User?> findById(String id) async {
// 查找用户逻辑
return null;
}
}
2. 构造函数最佳实践
dart
class Product {
final String id;
final String name;
final double price;
final DateTime createdAt;
// 主构造函数:必需参数
Product({
required this.id,
required this.name,
required this.price,
}) : createdAt = DateTime.now();
// 命名构造函数:特殊场景
Product.withTimestamp({
required this.id,
required this.name,
required this.price,
required this.createdAt,
});
// 工厂构造函数:复杂创建逻辑
factory Product.fromJson(Map<String, dynamic> json) {
return Product.withTimestamp(
id: json['id'],
name: json['name'],
price: json['price'].toDouble(),
createdAt: DateTime.parse(json['created_at']),
);
}
// 复制构造函数
Product copyWith({
String? name,
double? price,
}) {
return Product.withTimestamp(
id: id,
name: name ?? this.name,
price: price ?? this.price,
createdAt: createdAt,
);
}
}
3. 错误处理最佳实践
dart
class BankAccount {
final String accountNumber;
double _balance;
BankAccount(this.accountNumber, this._balance) {
if (_balance < 0) {
throw ArgumentError('初始余额不能为负数');
}
}
double get balance => _balance;
void deposit(double amount) {
if (amount <= 0) {
throw ArgumentError('存款金额必须大于0');
}
_balance += amount;
}
void withdraw(double amount) {
if (amount <= 0) {
throw ArgumentError('取款金额必须大于0');
}
if (amount > _balance) {
throw StateError('余额不足');
}
_balance -= amount;
}
// 安全的取款方法
bool tryWithdraw(double amount) {
try {
withdraw(amount);
return true;
} catch (e) {
return false;
}
}
}
4. 不可变性最佳实践
dart
// ✅ 不可变类
class ImmutablePoint {
final double x;
final double y;
const ImmutablePoint(this.x, this.y);
// 返回新实例而不是修改当前实例
ImmutablePoint translate(double dx, double dy) {
return ImmutablePoint(x + dx, y + dy);
}
ImmutablePoint scale(double factor) {
return ImmutablePoint(x * factor, y * factor);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ImmutablePoint && x == other.x && y == other.y;
@override
int get hashCode => Object.hash(x, y);
@override
String toString() => 'Point($x, $y)';
}
5. 文档和测试
dart
/// 表示一个二维向量的不可变类
///
/// 这个类提供了基本的向量运算,包括加法、减法、点积等。
/// 所有操作都返回新的向量实例,不会修改原有向量。
///
/// 示例用法:
/// ```dart
/// var v1 = Vector2D(3, 4);
/// var v2 = Vector2D(1, 2);
/// var sum = v1 + v2; // Vector2D(4, 6)
/// print(v1.magnitude); // 5.0
/// ```
class Vector2D {
/// X坐标分量
final double x;
/// Y坐标分量
final double y;
/// 创建一个新的二维向量
///
/// [x] X坐标分量
/// [y] Y坐标分量
const Vector2D(this.x, this.y);
/// 零向量常量
static const Vector2D zero = Vector2D(0, 0);
/// 单位向量常量
static const Vector2D unitX = Vector2D(1, 0);
static const Vector2D unitY = Vector2D(0, 1);
/// 向量的模长(大小)
double get magnitude => math.sqrt(x * x + y * y);
/// 向量加法
///
/// 返回两个向量相加的结果
Vector2D operator +(Vector2D other) => Vector2D(x + other.x, y + other.y);
/// 计算两个向量的点积
///
/// 点积的几何意义是两个向量的模长乘积再乘以它们夹角的余弦值
double dot(Vector2D other) => x * other.x + y * other.y;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Vector2D && x == other.x && y == other.y;
@override
int get hashCode => Object.hash(x, y);
@override
String toString() => 'Vector2D($x, $y)';
}
总结
Dart的类系统提供了丰富而强大的面向对象编程能力。通过掌握以下关键概念:
- 类的基础语法:属性、方法、构造函数
- 继承机制:单继承、方法重写、super调用
- 接口实现:隐式接口、多接口实现
- 混入系统:代码复用、线性化
- 泛型支持:类型安全、代码复用
- 操作符重载:自然的语法表达
- 扩展方法:为现有类型添加功能
结合最佳实践和性能考虑,可以编写出高质量、可维护的Dart代码。记住要遵循单一职责原则,合理使用不可变性,并注意避免常见的陷阱。
本文档基于Dart 3.x版本整理,涵盖了类系统的核心概念和实际应用场景。