Dart 对象
最后修改日期:2025 年 6 月 4 日
本 Dart 对象教程探讨了如何在 Dart 编程语言中使用对象。对象是 Dart 程序的构建块,它们结合了数据和行为,以创建模块化、可重用的代码。
理解对象
在 Dart 中,对象是程序的基本单元,封装了数据和方法。数据,也称为实例变量,以及方法,也称为成员函数,统称为对象的成员。对象通过它们的方法相互交互,从而实现数据处理和通信。
创建对象涉及两个步骤:定义类和实例化它。类充当蓝图,概述了该类所有对象共享的状态和行为。对象,或实例,是使用 new 关键字在运行时从类创建的,而 new 关键字在 Dart 2.0 及更高版本中是可选的。我们使用点 (.) 运算符来访问对象的实例变量或方法。
面向对象编程 (OOP) 是一种利用对象及其交互来设计健壮的应用程序和程序的范例。
Dart 对象
在 Dart 中,一切皆对象,包括数字和字符串等字面量,这使 Dart 与许多其他编程语言区分开来。
class Being {}
void main() {
var b = Being();
print(b.hashCode);
print("falcon".toUpperCase());
print(2.isNegative);
print(b.runtimeType);
print(2.runtimeType);
}
此示例演示了在 Dart 中使用各种对象。
class Being {}
class 关键字定义了对象的模板。在这里,Being 类是空的,但仍然是功能性的。
var b = Being();
创建了一个新的 Being 实例。在现代 Dart 中,new 关键字是可选的。
print(b.hashCode);
即使是空对象也继承了 Dart 的 Object 类的方法和属性,例如 hashCode。
print("falcon".toUpperCase());
字符串字面量 "falcon" 是一个具有 toUpperCase 等方法的对象,展示了 Dart 的面向对象特性。
print(2.isNegative);
数字字面量,例如 2,也是具有 isNegative 等属性的对象。
print(b.runtimeType); print(2.runtimeType);
runtimeType 属性会在运行时显示每个对象的类型。
$ dart main.dart 511903303 FALCON false Being int
Dart 对象属性
对象属性,或实例变量,用于存储每个类实例特有的数据。每个对象都维护这些变量的独立副本。Dart 会自动为所有实例变量生成 getter 方法,并为非 final 变量生成 setter 方法。
class Person {
String? name;
String? occupation;
}
void main() {
var p1 = Person();
p1.name = "John Doe";
p1.occupation = "gardener";
var p2 = Person();
p2.name = "Roger Roe";
p2.occupation = "driver";
print("${p1.name} is a ${p1.occupation}");
print("${p2.name} is a ${p2.occupation}");
}
此示例定义了一个具有两个属性:name 和 occupation 的 Person 类。
var p1 = Person(); p1.name = "John Doe"; p1.occupation = "gardener";
创建了一个 Person 对象,并通过点运算符设置了其属性。
var p2 = Person(); p2.name = "Roger Roe"; p2.occupation = "driver";
创建了第二个、唯一的 Person 对象,并设置了不同的属性值。
print("${p1.name} is a ${p1.occupation}");
print("${p2.name} is a ${p2.occupation}");
打印了两个对象的属性,展示了它们各自的状态。
$ dart main.dart John Doe is a gardener Roger Roe is a driver
Dart 级联运算符
级联运算符 (..) 允许以简洁的方式对同一对象执行多个操作,从而提高了代码的可读性。
class User {
String? fname;
String? lname;
String? occupation;
@override
String toString() => "$fname $lname is a $occupation";
}
void main() {
var u = User()
..fname = "Roger"
..lname = "Roe"
..occupation = "driver";
print(u);
}
此示例使用级联运算符在单个表达式中初始化 User 对象的属性。
$ dart main.dart Roger Roe is a driver
Dart 对象方法
方法是在类中定义的函数,它们操作对象的属性,从而促进代码的模块化和可重用性。
import 'dart:math';
class Circle {
int radius;
Circle(this.radius);
double area() => pi * radius * radius;
}
void main() {
var c = Circle(5);
print(c.area());
}
此示例定义了一个具有 area 方法来计算圆面积的 Circle 类。
double area() => pi * radius * radius;
area 方法使用 dart:math 库中的 pi 常量来计算面积。
var c = Circle(5);
创建了一个半径为 5 的 Circle 对象。
print(c.area());
使用点运算符调用 area 方法来计算并打印面积。
$ dart main.dart 78.53981633974483
Dart 对象构造函数
构造函数是在创建对象时自动调用的特殊方法,用于初始化对象的状态。Dart 支持命名构造函数和工厂构造函数,它们不返回值。
命名构造函数共享类的名称,通常用于直接初始化。
class User {
String name;
String occupation;
User(this.name, this.occupation);
}
void main() {
var u1 = User("John Doe", "gardener");
var u2 = User("Roger Roe", "driver");
print("${u1.name} is a ${u1.occupation}");
print("${u2.name} is a ${u2.occupation}");
}
此示例使用命名构造函数来初始化 User 对象的属性。
User(this.name, this.occupation);
构造函数使用自动初始化程序来设置 name 和 occupation 属性。
var u1 = User("John Doe", "gardener");
创建了一个 User 对象,并将值传递给构造函数。
$ dart main.dart John Doe is a gardener Roger Roe is a driver
工厂构造函数,使用 factory 关键字定义,允许自定义对象创建逻辑,例如缓存或条件实例化。它们可以返回现有对象,并且在设计模式中很有用。
import 'dart:math';
abstract class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle(4);
if (type == 'square') return Square(4);
if (type == 'triangle') return Triangle(4);
throw Exception("Unknown shape");
}
num get area;
}
class Circle implements Shape {
final num radius;
Circle(this.radius);
num get area => pi * pow(radius, 2);
}
class Square implements Shape {
final num side;
Square(this.side);
num get area => pow(side, 2);
}
class Triangle implements Shape {
final num side;
Triangle(this.side);
num get area => pow(side, 2) / 2;
}
void main() {
print(Shape('circle').area);
print(Shape('square').area);
print(Shape('triangle').area);
}
此示例在抽象 Shape 类中使用工厂构造函数,根据类型参数创建不同的形状。
$ dart main.dart 50.26548245743669 16 8.0
Dart toString 方法
每个 Dart 对象都从 Object 类继承 toString 方法,该方法提供人类可读的字符串表示形式。对对象调用 print 会隐式调用 toString。
class User {
String name;
String occupation;
User(this.name, this.occupation);
@override
String toString() => "$name is a $occupation";
}
void main() {
var u1 = User("John Doe", "gardener");
var u2 = User("Roger Roe", "driver");
print(u1);
print(u2);
}
此示例在 User 类中重写了 toString 方法,以提供自定义的字符串表示形式。
@override String toString() => "$name is a $occupation";
重写的 toString 方法返回一个格式化的字符串,其中包含用户的姓名和职业。
print(u1); print(u2);
打印对象会自动调用它们的 toString 方法。
$ dart main.dart John Doe is a gardener Roger Roe is a driver
Dart 自动初始化程序
Dart 支持使用自动初始化程序的简洁构造函数语法,这可以简化属性初始化,而无需显式的赋值语句。
class User {
String name;
String occupation;
User(this.name, this.occupation);
}
void main() {
var u1 = User("John Doe", "gardener");
var u2 = User("Roger Roe", "driver");
print("${u1.name} is a ${u1.occupation}");
print("${u2.name} is a ${u2.occupation}");
}
此示例在 User 类的构造函数中演示了自动初始化程序,推断数据类型并减少了样板代码。
Dart 命名参数
命名参数,用花括号 {} 表示,允许灵活的构造函数调用,其中参数通过名称指定,从而提高了代码的清晰度。
class User {
String? name;
String? occupation;
User({this.name, this.occupation});
@override
String toString() => "$name is a $occupation";
}
void main() {
var u1 = User(name: "John Doe", occupation: "gardener");
print(u1);
}
此示例使用命名参数初始化 User 对象,使代码更具可读性和灵活性。
Dart 对象继承
继承允许新类建立在现有类的基础上,创建派生类来扩展或覆盖基类的功能。Dart 使用 extends 关键字进行继承。
class Being {
static int count = 0;
Being() {
count++;
print("Being is created");
}
void getCount() => print("There are $count Beings\n");
}
class Human extends Being {
Human() {
print("Human is created");
}
}
class Animal extends Being {
Animal() {
print("Animal is created");
}
}
class Dog extends Animal {
Dog() {
print("Dog is created");
}
}
void main() {
Human();
var dog = Dog();
dog.getCount();
}
此示例演示了一个类层次结构,其中 Human 和 Animal 继承自 Being,而 Dog 继承自 Animal。一个静态变量用于跟踪实例计数。
static int count = 0;
静态 count 变量在 Being 类及其子类的所有实例之间共享。
Being() {
count++;
print("Being is created");
}
Being 构造函数在每次创建实例时递增计数并打印一条消息。
class Animal extends Being {
...
class Dog extends Animal {
...
Animal 和 Dog 类分别继承自它们的父类,形成多级层次结构。
Human(); var dog = Dog(); dog.getCount();
创建了 Human 和 Dog 的实例,并且 getCount 方法显示了 Being 实例的总数。
$ dart main.dart Being is created Human is created Being is created Animal is created Dog is created There are 2 Beings
Dart 检查类型
Dart 的 is 关键字在运行时检查对象的类型,这对于动态代码中的类型验证很有用。
class Person {}
class Student {}
void main() {
var p = Person();
var s = Student();
print(p is Person);
print(s is Person);
print(p is Object);
print(s is Object);
print(2 is int);
print(2 is Object);
}
此示例使用 is 关键字检查各种对象的类型。
print(p is Person);
这会检查 p 是否是 Person 的实例,结果返回 true。
print(s is Person);
这会检查 s 是否是 Person,结果返回 false,因为 s 是 Student。
print(2 is Object);
由于所有 Dart 对象都继承自 Object,因此此检查对于数字字面量 2 返回 true。
$ dart main.dart true false true true true true
Dart Getter 和 Setter
Dart 允许显式定义 getter 和 setter 来控制对对象属性的访问,从而提供封装和验证逻辑。
class Account {
double _balance = 0.0;
double get balance => _balance;
set balance(double value) {
if (value >= 0) {
_balance = value;
} else {
throw Exception("Balance cannot be negative");
}
}
}
void main() {
var account = Account();
account.balance = 100.0;
print("Balance: ${account.balance}");
try {
account.balance = -50.0;
} catch (e) {
print(e);
}
}
此示例定义了一个 Account 类,其中包含一个私有的 _balance 属性,该属性通过 getter 和 setter 方法进行访问。
double get balance => _balance;
getter 返回私有的 _balance 值。
set balance(double value) {
if (value >= 0) {
_balance = value;
} else {
throw Exception("Balance cannot be negative");
}
}
setter 验证余额是否为非负数,然后再进行更新。
$ dart main.dart Balance: 100.0 Exception: Balance cannot be negative
Dart 方法重写
方法重写允许子类提供其超类中定义的方法的特定实现,从而实现多态行为。
class Animal {
void makeSound() => print("Some generic sound");
}
class Dog extends Animal {
@override
void makeSound() => print("Woof!");
}
class Cat extends Animal {
@override
void makeSound() => print("Meow!");
}
void main() {
var dog = Dog();
var cat = Cat();
dog.makeSound();
cat.makeSound();
}
此示例演示了在具有 Animal、Dog 和 Cat 的类层次结构中进行方法重写。
@override
void makeSound() => print("Woof!");
Dog 类重写了 makeSound 方法以提供特定实现。
$ dart main.dart Woof! Meow!
Dart Mixins
Dart 中的 Mixin 允许通过添加功能到类而不使用继承来实现代码重用,从而促进了模块化和灵活性。
mixin Flyable {
void fly() => print("Flying...");
}
class Bird with Flyable {
String name;
Bird(this.name);
}
void main() {
var eagle = Bird("Eagle");
eagle.fly();
print("${eagle.name} is soaring high!");
}
此示例使用 Flyable mixin 为 Bird 类添加飞行行为。
mixin Flyable {
void fly() => print("Flying...");
}
Flyable mixin 定义了一个 fly 方法,可以与任何类共享。
class Bird with Flyable {
Bird 类使用 with 关键字合并了 Flyable mixin。
$ dart main.dart Flying... Eagle is soaring high!
Dart 抽象类
Dart 中的抽象类不能被实例化,用于定义接口或为子类提供共享功能。
abstract class Vehicle {
void startEngine();
}
class Car extends Vehicle {
@override
void startEngine() => print("Car engine started");
}
class Bike extends Vehicle {
@override
void startEngine() => print("Bike engine started");
}
void main() {
var car = Car();
var bike = Bike();
car.startEngine();
bike.startEngine();
}
此示例定义了一个抽象 Vehicle 类,以及具体的子类 Car 和 Bike。
abstract class Vehicle {
void startEngine();
}
抽象 Vehicle 类声明了一个 startEngine 方法,子类必须实现该方法。
$ dart main.dart Car engine started Bike engine started
来源
本教程探讨了使用 Dart 中对象的基础知识,包括属性、方法、构造函数、继承等。
作者
探索 所有 Dart 教程。