Dart中的类

使用关键字class声明一个类。可以使用new创建构造函数,所有的对象默认都集成Object类

  1. void main() {
  2. LGPerson p = LGPerson();
  3. p.run();
  4. }
  5. class LGPerson {
  6. String? name;
  7. int? age;
  8. void run() {
  9. print('name: $name, age: $age');
  10. }
  11. }

image.png
赋值的话使用

  1. p.name = 'hello';
  2. p.age = 18;

在Dart中默认会生成getter和setter方法,属性和方法都通过.语法来访问。注意:final修饰的属性必须要有初始值。在Dart中方法是不能重载的。本质的原理是方法的名称是寻找方法的唯一标识

  1. class LGPerson {
  2. String? name;
  3. int? age;
  4. void run() {
  5. print('name: $name, age: $age');
  6. }
  7. int run() {
  8. return 10;
  9. }
  10. }

image.png
在Dart中,用一份文件下里面的方法都是可以访问的,是不在私有化的。对于不想暴露出来的属性和方法我们可以这么处理:新创建一个Dart文件,注意命名规范。
image.png
然后把Person类放到这里的lg_person.dart文件里,此时main中引用会报错:找不到该文件。解决的办法是,选中main中的LGPerson然后option + 回车,这里就自动导入了头文件import lg_person.dart,
对于类中的属性和方法,只要加上_前缀外界就不能访问。但是在lg_person.dart这个文件内是可以访问。所谓的私有其实是跨文件。

  1. class LGPerson {
  2. String? name;
  3. int? age;
  4. void _run() {
  5. print('name: $name, age: $age');
  6. }
  7. }

image.png

Dart中的构造函数

在Dart中默认会生成构造函数,但是我们也可以自定义

  1. class LGPerson {
  2. String? _name;
  3. int? _age;
  4. void _run() {
  5. print('name: $_name, age: $_age');
  6. }
  7. LGPerson(int age, String name) {
  8. _name = name;
  9. _age = age;
  10. _run();
  11. }
  12. }

这里需要注意一点:如果构造函数的形参和属性保持一致的话,那么外层LGPerson p = LGPerson(18, 'hello')赋值是不会成功的
image.png
Dart有一个语法糖写法更优美, 而且String也不用给默认值。

  1. class LGPerson {
  2. String _name;
  3. int _age;
  4. void run() {
  5. print('name: $_name, age: $_age');
  6. }
  7. LGPerson(this._age, this._name);
  8. }

属性一旦使用final修饰的话,这个就是个最终变量,所以中途不能被修改。
image.png
final修饰的成员变量可以不用一开始就给初始值,可以在构造函数中赋值。final实际应用场景:当一个对象的所有成员属性都是使用final来修饰的话,那么这个对象可以被创建为常量对象,使用const修饰构造函数。

  1. class LGPerson {
  2. final String _name;
  3. final int _age;
  4. void run() {
  5. print('name: $_name, age: $_age');
  6. }
  7. const LGPerson(this._age, this._name); /// const修饰构造函数
  8. // 命名构造函数
  9. const LGPerson.withName(this._name, this._age);
  10. }

构造函数的另外一种写法:命名构造函数

  1. // 命名构造函数
  2. LGPerson.withName(this._name, this._age);

Dart的工厂构造&单例对象

  1. void factoryDemo(){
  2. FactoryClass fact1 = FactoryClass('hello',12);
  3. FactoryClass fact2 = FactoryClass('hello',12);
  4. print(fact1 == fact2);
  5. }

如果想让fact1 == fact2有什么办法?我们想到上面介绍的常量对象,那么来试一下

  1. class FactoryClass {
  2. final String name;
  3. final int age;
  4. const FactoryClass(this.name, this.age);
  5. }

image.png
很明显使用常量对象并不可以,那么怎么做呢

  1. class FactoryClass {
  2. // 需要一个单例对象
  3. static FactoryClass _instance;
  4. factory FactoryClass(){
  5. if(_instance == null){
  6. _instance = FactoryClass._init()
  7. }
  8. return _instance!;
  9. }
  10. // 私有的命名构造函数
  11. FactoryClass._init();
  12. }

image.png
注意:在Dart中,我们发现构造函数是没有return的,如果想要return的话需要加上关键字factory,修改之后成了下面这样:

  1. class FactoryClass {
  2. // 需要一个单例对象
  3. static FactoryClass? _instance;
  4. factory FactoryClass(){
  5. if(_instance == null){
  6. _instance = FactoryClass._init();
  7. }
  8. return _instance!;
  9. }
  10. // 私有的命名构造函数
  11. FactoryClass._init();
  12. }

我们其实还可以优化:

  1. class FactoryClass {
  2. // 需要一个单例对象
  3. static FactoryClass? _instance;
  4. // 利用前面学过的为空赋值运算“??=”
  5. factory FactoryClass(){
  6. _instance ??= FactoryClass._init();
  7. return _instance;
  8. }
  9. // 私有的命名构造函数
  10. FactoryClass._init();
  11. }

继续化简能够得到:

  1. class FactoryClass {
  2. // 需要一个单例对象
  3. static FactoryClass? _instance;
  4. factory FactoryClass(){
  5. return _instance ??= FactoryClass._init();;
  6. }
  7. // 私有的命名构造函数
  8. FactoryClass._init();
  9. }

还能继续化简,当方法的执行语句只有一句的时候,可以使用箭头函数=>表达式

  1. class FactoryClass {
  2. // 需要一个单例对象
  3. static FactoryClass? _instance;
  4. factory FactoryClass() => _instance ??= FactoryClass._init();
  5. // 私有的命名构造函数
  6. FactoryClass._init();
  7. }

此时再次打印来验证单例是否创建成功
image.png

初始化列表

初始化列表的目的:给final变量赋值,校验传递的参数。

  1. class LGPerson {
  2. String name;
  3. int age;
  4. final height;
  5. LGPerson(this.name, this.age, int h):
  6. height = h, assert(h > 0){
  7. print('name:$name,age:$age,height:$height');
  8. }
  9. }
  10. void factoryDemo(){
  11. LGPerson p = LGPerson('hello', 18, 0);
  12. }

这里报错,是因为校验h>0没有通过
image.png

  1. LGPerson p = LGPerson('hello', 18, 1);

image.png