likes
comments
collection
share

简单易懂的Dart基础语法,类和对象。

作者站长头像
站长
· 阅读数 5

Dart中的类

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

void main() {
  LGPerson p = LGPerson();
  p.run();
}
class LGPerson {
  String? name;
  int? age;
  void run() {
    print('name: $name, age: $age');
  }
}

简单易懂的Dart基础语法,类和对象。

赋值的话使用点语法:

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

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

class LGPerson {
  String? name;
  int? age;
  void run() {
    print('name: $name, age: $age');
  }
  int run() {
    return 10;
  }
}

简单易懂的Dart基础语法,类和对象。

Dart中,用一份文件下里面的方法都是可以访问的,是不在私有化的。对于不想暴露出来的属性和方法我们可以这么处理:新创建一个Dart文件,注意命名规范。

简单易懂的Dart基础语法,类和对象。

然后把Person类放到这里的lg_person.dart文件里,此时main中引用会报错:找不到该文件。解决的办法是,选中main中的LGPerson然后option + 回车,这里就自动导入了头文件import lg_person.dart, 对于类中的属性和方法,只要加上_前缀外界就不能访问。但是在lg_person.dart这个文件内是可以访问。所谓的私有其实是跨文件。

class LGPerson {
  String? name;
  int? age;
  void _run() {
    print('name: $name, age: $age');
  }
}

简单易懂的Dart基础语法,类和对象。

Dart中的构造函数

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

class LGPerson {
  String? _name;
  int? _age;
  void _run() {
    print('name: $_name, age: $_age');
  }
  LGPerson(int age, String name) {
    _name = name;
    _age = age;
    _run();
  }
}

这里需要注意一点:如果构造函数的形参和属性保持一致的话,那么外层LGPerson p = LGPerson(18, 'hello')赋值是不会成功的

简单易懂的Dart基础语法,类和对象。

Dart有一个语法糖写法更优美, 而且String也不用给默认值。

class LGPerson {
  String _name;
  int _age;
  void run() {
    print('name: $_name, age: $_age');
  }
  LGPerson(this._age, this._name);
}

属性一旦使用final修饰的话,这个就是个最终变量,所以中途不能被修改。

简单易懂的Dart基础语法,类和对象。

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

class LGPerson {
  final String _name;
  final int _age;
  void run() {
    print('name: $_name, age: $_age');
  }
  const LGPerson(this._age, this._name); /// const修饰构造函数
  // 命名构造函数
  const LGPerson.withName(this._name, this._age);
}

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

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

#### Dart的工厂构造&单例对象

void factoryDemo(){
  FactoryClass fact1 = FactoryClass('hello',12);
  FactoryClass fact2 = FactoryClass('hello',12);
  print(fact1 == fact2);
}

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

class FactoryClass {
  final String name;
  final int age;
  const FactoryClass(this.name, this.age);
}

简单易懂的Dart基础语法,类和对象。

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

class FactoryClass {
  // 需要一个单例对象
  static FactoryClass _instance;
  factory FactoryClass(){
    if(_instance == null){
      _instance = FactoryClass._init()
    }
    return _instance!;
  }

  // 私有的命名构造函数
  FactoryClass._init();
}

简单易懂的Dart基础语法,类和对象。

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

class FactoryClass {
  // 需要一个单例对象
  static FactoryClass? _instance;
  factory FactoryClass(){
    if(_instance == null){
      _instance = FactoryClass._init();
    }
    return _instance!;
  }

  // 私有的命名构造函数
  FactoryClass._init();
}

我们其实还可以优化:

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

继续化简能够得到:

class FactoryClass {
  // 需要一个单例对象
  static FactoryClass? _instance;
  factory FactoryClass(){
    return _instance ??= FactoryClass._init();;
  }
  // 私有的命名构造函数
  FactoryClass._init();
}

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

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

此时再次打印来验证单例是否创建成功 简单易懂的Dart基础语法,类和对象。

初始化列表

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

class LGPerson {
  String name;
  int age;
  final height;
  LGPerson(this.name, this.age, int h):
      height = h, assert(h > 0){
    print('name:$name,age:$age,height:$height');
  }
}

void factoryDemo(){
  LGPerson p = LGPerson('hello', 18, 0);
}

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

简单易懂的Dart基础语法,类和对象。

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

简单易懂的Dart基础语法,类和对象。