Flutter---构造函数

基本构造函数

Dart 复制代码
class Person {
  String name;
  int age;
  
  // 普通构造函数
  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

 // 简化写法:直接把参数赋值给成员变量
 // Person(this.name, this.age);  // ← 一行搞定!
}

void main() {
  Person p = Person("张三", 25);
  print("${p.name}, ${p.age}");  // 张三, 25
}

命名构造函数

命名构造函数就是有名字的构造函数 ,可以有多个,用 . 区分

Dart 复制代码
class Person {
  String name;
  int age;
  
  // 默认构造函数
  Person(this.name, this.age);
  
  // 命名构造函数1:从地图创建
  Person.fromMap(Map<String, dynamic> map) 
      : name = map['name'],
        age = map['age'];
  
  // 命名构造函数2:从 JSON 创建
  Person.fromJson(String jsonString) 
      : name = "解析出的名字",
        age = 0;
  
  // 命名构造函数3:创建默认人员
  Person.guest() 
      : name = "游客",
        age = 0;
}

void main() {
  // 使用不同的构造函数创建对象
  Person p1 = Person("张三", 25);                    // 普通
  Person p2 = Person.fromMap({'name': '李四', 'age': 30});  // 命名
  Person p3 = Person.guest();                       // 命名
  
  print(p1.name);  // 张三
  print(p2.name);  // 李四
  print(p3.name);  // 游客
}

初始化列表

初始化列表是 : 后面的部分,在构造函数体执行前运行

Dart 复制代码
class Person {
  final String name;  // final 变量必须初始化
  final int age;
  
  // 初始化列表:在构造函数体之前初始化 final 变量
  Person.fromMap(Map<String, dynamic> map) 
      : name = map['name'],      // ← 初始化列表
        age = map['age'] {       // ← 这里不能写赋值了
    // 构造函数体
    print("对象创建完成");
  }
}

初始化列表的优势

Dart 复制代码
class Example {
  final int a;
  int b;
  
  // ❌ 错误:final 变量不能在构造函数体中赋值
  Example(int value) {
    a = value;  // 编译错误!
    b = value;  // 普通变量可以
  }
  
  // ✅ 正确:final 变量必须在初始化列表赋值
  Example(int value) : a = value {  // ← 这里赋值
    b = value;
  }
}

使用super,调用父类构造函数

Dart 复制代码
// 父类
class Animal {
  String type;
  
  Animal(this.type) {
    print("Animal 构造函数");
  }
  
  Animal.named(this.type) {
    print("Animal 命名构造函数");
  }
}

// 子类
class Dog extends Animal {
  String name;
  
  // 调用父类普通构造函数
  Dog(String name, String type) : super(type) {
    this.name = name;
    print("Dog 构造函数");
  }
  
  // 调用父类命名构造函数
  Dog.fromMap(Map<String, dynamic> map) 
      : name = map['name'], //初始化自己的属性
        super.named(map['type']) { //初始化父类的属性
    print("Dog 命名构造函数");
  }
}

void main() {
  Dog d1 = Dog("旺财", "犬科");
  // 输出:
  // Animal 构造函数
  // Dog 构造函数
  
  Dog d2 = Dog.fromMap({'name': '小黑', 'type': '犬科'});
  // 输出:
  // Animal 命名构造函数
  // Dog 命名构造函数
}

疑问点

Dart 复制代码
1.子类为什么要调用父类的构造函数?
答:子类必须调用父类构造函数,因为父类的属性需要被初始化!

2.谁负责初始化父类属性?
父类自己的构造函数

3.子类能直接给父类属性赋值吗?
不能,因为父类属性可能是final

4.怎么调用
在初始化列表中用super(...)

可视化理解

相关推荐
ZC跨境爬虫7 分钟前
跟着 MDN 学 HTML day_33:(Attr 接口与属性节点的深入理解)
前端·javascript·ui·html·音视频·html5
skywalk816315 分钟前
Trae生成的中文编程语言关键字(如“定“、“函“、“印“等)需要和标识符之间用 空格 隔开,以确保正确识别
服务器·开发语言·编程
红色的小鳄鱼21 分钟前
前端面试js手写
开发语言·前端·javascript
海盗123428 分钟前
C#中的IEqualityComparer<T>使用
开发语言·c#
江公望38 分钟前
Qt QSharedPointer用法,10分钟讲清楚
开发语言·qt
web行路人39 分钟前
前端对Commands(斜杠命令)一些常用
前端·javascript·vue.js·vue
竹林81841 分钟前
用 ethers.js 连 MetaMask 做钱包登录,我踩了三个坑才搞定跨页面状态同步
前端·javascript
阿星做前端43 分钟前
重度 AI 编程用户的一天:我怎么把 Claude Code / Codex 工作流搬进浏览器工作台
前端·javascript·后端
风止何安啊43 分钟前
手写 URL 解析器,面试官到底想考什么?
前端·javascript·面试
月落归舟44 分钟前
深入理解Java适配器模式,彻底搞懂设计思想
java·开发语言·适配器模式