Dart | class 详解

Dart | class 详解

💡 原文中文,约6000字,阅读约需15分钟。
📝

内容提要

Dart 是面向对象语言,所有类派生自 Object,支持 mixin 复用。用点访问成员,?. 避免 null 报错。构造器可用语法糖 Point(this.x, this.y),支持具名、重定向、工厂、定值构造器。子类不继承构造器,需手动调用 super。类即隐性接口,可用 implements。还介绍了 getter/setter、抽象类、枚举、静态成员等。

🔎

延伸解读

构造器调用顺序与继承限制

子类不会继承父类构造器,包括具名构造器。当子类实例化时,会先执行初始化列表,然后调用父类的无参数构造器,最后执行自己的构造器体。如果父类没有无参数构造器,子类必须通过 super 显式调用父类的其他构造器,否则编译报错。理解这一顺序有助于避免初始化逻辑错误。

工厂构造器的缓存应用

工厂构造器不要求返回新实例,可以返回缓存对象或子类实例。文中 Logger 示例使用静态 Map 缓存已创建的 Logger,避免重复实例化。这种模式适合需要控制实例数量或复用对象的场景,但要注意缓存可能引起内存泄漏,需根据实际需求管理生命周期。

隐性接口与 implements 的灵活运用

Dart 中每个类都隐式定义了一个接口,包含实例成员和方法(构造器除外)。通过 implements 可以实现该接口,而不继承实现。这允许在不相关的类之间共享 API 约定,类似其他语言的接口。但需注意,实现接口时必须重写所有成员,包括私有成员(如果跨库则不可见),否则会编译错误。

空安全操作符 ?. 的实用价值

使用 ?. 代替 . 可以在对象为 null 时避免抛出异常,直接返回 null。这在链式调用中尤其有用,例如 p?.y = 4 在 p 为 null 时不会报错。但需注意,如果后续操作依赖于非空结果,仍需进行空值检查,否则可能将 null 传递到其他逻辑中,导致难以排查的问题。

❓

Q&A

Dart 中如何安全地访问可能为 null 的对象的成员?

使用 ?. 代替 . 来访问成员,这样即使对象为 null 也不会报错。例如:p?.y = 4;

Dart 的构造函数有哪些类型?

Dart 支持默认构造函数、具名构造函数、重定向构造函数、工厂构造函数和定值构造函数。默认构造函数在未声明任何构造函数时自动添加,无参数且不具名。具名构造函数使用 ClassName.identifier 形式。重定向构造函数将调用委托给同一类的另一个构造函数。工厂构造函数可以返回缓存实例或子类实例。定值构造函数用于创建编译时常量对象,要求所有实例变量为 final。

Dart 中子类如何调用父类的具名构造函数?

子类不会继承父类的构造函数,如果父类只有具名构造函数,子类必须手动调用 super 来执行父类的构造函数。例如:Employee.fromJson(Map data) : super.fromJson(data) { ... }

Dart 中的 getter 和 setter 有什么作用?如何定义?

getter 和 setter 用于定义计算属性,可以像访问实例变量一样访问。使用 get 和 set 关键字定义,例如:num get right => left + width; set right(num value) => left = value - width;

Dart 中的抽象类和接口有什么区别?

抽象类使用 abstract 关键字定义,不能实例化,可以包含抽象方法和具体方法。每个类都隐式定义了一个接口,只包含实例成员和方法,不包括构造函数。要实现接口,使用 implements 关键字。抽象类通常用于定义接口,而 implements 用于实现接口。

Dart 中枚举有哪些限制?

枚举不能继承、mixin 或 implement 其他枚举,也不能显式实例化枚举。

🏷️

标签

➡️

继续阅读