Flutter
已经是整整一年前的事情了,之后因为工作重心主要放在了React Native
开发形式上Flutter
, 也是计划系统性的从头开始重新学习Dart
和Flutter
Dart
笔记主要就是记录Dart
语言中的类和对象Dart
也是一门面向对象的开发语言,面向对象中非常重要的概念就是类,通过类的初始化创建一个对象
Dart
中,定义类用class
关键字Object
的, 格式如下:class 类名 { 类型 成员名; 返回值类型 方法名(参数列表) { 方法体 } } 复制代码
Dart
语言中, 在类中使用属性(成员/实例变量)时, 有必要时是通过this
获取的getsize
方法中并没有加this
Dart
的开发风格中,在方法中通常使用属性时,会省略this
,但是有命名冲突时,this
不能省略// 创建类 class Point { // 定义变量 int x; void getsize() { print('x = $x'); } } // 类的初始化 main(List<String> args) { // 从Dart2开始,new关键字可以省略 var point = new Point(); point.x = 1; point.getsize(); } 复制代码
Dart
语言中,如果类中没有明确指定构造方法时,将默认拥有一个无参的构造方法()point
对象调用的就是默认的无参构造方法Dart
本身不支持函数的重载, 所以如果我们明确的写一个默认的构造方法,就会和我们自定义的构造方法冲突class Student { String name; int age; Student(String name, int age) { this.name = name; this.age = age; } } 复制代码
Dart
提供了一种更加简洁的语法糖形式class Student1 { String name; int age; // 这里和上面的Studeng的构造方法等价 Student1(this.name, this.age); } 复制代码
Dart
又不支持函数的重载, 不能创建爱你相同名称不同参数的构造方法class Model { String name; int age; Model(this.name, this.age); // 命名构造方法 Model.withNameAndAge(String name, int age) { this.name = name; this.age = age; } // 命名构造方法 Model.initJson(Map<String, Object> map) { this.name = map['name']; this.age = map['age']; } } // 初始化对象 main() { // 普通构造方法 var model0 = Model('name', 12); // 命名构造方法 var model1 = Model.withNameAndAge('titan', 12); var model2 = Model.initJson({'name': 'jun', 'age': 18}); } 复制代码
几种方式定义的属性都是可变的, 如果定义的属性是final
不可重新赋值的又该如何实现
class Teacher { final String name; final int age; // 1. 这里会有一个错误提示: All final variables must be initialized, but 'age' and 'name' are not Teacher(String name, int age) { //2. 这里也会有一个错误提示: 'name' can't be used as a setter because it's final this.name = name; this.age = age; } } 复制代码
Dart
中在执行下面{ }
中的代码的时候, 表示Teacher
对象已经初始化完毕了{ }
之前, 必须保证name
和age
被初始化了final
修饰的属性是不可被重新赋值的, 所以才会报错class Size { final double width; final double height; final double area; // 命名可选参数 Size(this.width, this.height, { this.area = 10 }); } 复制代码
area
只能设置具体的数值, 不能设置表达式class Size { final double width; final double height; final double area; // 多个属性使用逗号分隔 Size(double width, double height): this.width = width, this.height = height, this.area = width * height; } 复制代码
name
变量来获取一个对象class Point { String name; int age; Point(this.name, this.age); // 重定向的构造方法 Point.fromName(String name): this(name, 0); } // 使用方法 var point = Point.fromName("name"); print(point.age); // 输出: 0 复制代码
Dart
中判断两个对象是否是同一个的方法是通过函数identical
判断, 返回值是一个布尔值// 普通构造函数 class Person { String name; int age; Person(this.name, this.age); } // 初始化列表 class Size { final double width; final double height; final double area; // 多个属性使用逗号分隔 Size(double width, double height): this.width = width, this.height = height, this.area = width * height; } main(List<String> args) { var p1 = Person("name", 10); var p2 = Person("name", 10); // 判断两个对象是不是同一个 print(identical(p1, p2)); /// false var s1 = Size(10, 20); var s2 = Size(10, 20); // 判断两个对象是不是同一个 print(identical(s1, s2)); /// false } 复制代码
Dart
中如果将构造方法前加const
进行修饰,那么可以保证相同的参数,创建出来的对象是相同的// 常量构造方法 class Teacher { final String name; const Teacher(this.name); } main(List<String> args) { // 常量构造方法 // 这里的const不可以省略 var t1 = const Teacher("name"); var t2 = const Teacher("name"); print(identical(t1, t2)); /// true // 这里的const可以省略 const t3 = Teacher("name"); const t4 = Teacher("name"); print(identical(t3, t4)); /// true print(identical(t1, t4)); /// true } 复制代码
常量构造方法有一些注意点:
final
修饰的.new
关键字,而是使用const
关键字const
修饰的标识符时,const
可以省略.Dart
提供了factory
关键字, 用于通过工厂去获取对象return
main(List<String> args) { var p1 = Person.fromName("titan"); var p2 = Person.fromName("titan"); print(identical(p1, p2)); // true } class Person { String name; // 用于缓存创建的对象, 避免大量的创建和销毁对象 static final Map<String, Person> _cache = <String, Person>{}; factory Person.fromName(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else { final p = Person(name); _cache[name] = p; return p; } } Person(this.name); } 复制代码
Dart
中类定义的属性默认是可以直接被外界访问的Dart
中也存在setter
和getter
方法, 用于监听累的属性被访问的过程main() { var people = People('top'); people.setName = 'top'; print(people.getName); print(people.name); var person = Person('titan'); person.setName = 'jun'; print(person.getName); } class People { String name; // setter set setName(String value) { this.name = value; } // getter String get getName { return 'titanjun'; } People(this.name); } 复制代码
setName
和getName
是自定义的, 你也可以命名为setterName
和getterName
等class Person { String name; // setter set setName(String value) => this.name = value; // getter String get getName => 'titanjun'; Person(this.name); } 复制代码
Dart
中同样支持类的继承, 继承使用extends
关键字,子类中使用super
来访问父类super
显式调用父类的某个构造方法class People { String name; People(this.name); void eat() { print('people -- eat'); } } class Person extends People { int age; Person(String name, int age): this.age = age, super(name); @override void eat() { // 这里的super, 看个人需求是否调用 super.eat(); print('Person -- eat'); } } main(List<String> args) { var people = People('name'); people.eat(); var person = Person("top", 10); person.eat(); } 复制代码
Dart
中抽象类是使用abstract
声明的类Dart
中没有具体实现的方法(没有方法体),就是抽象方法abstract class Size { int width; int height; Size(this.width, this.height); void getSize(); int getArea() { return this.width * this.height; } } class Area extends Size { @override void getSize() { print('width = $width, height = $height'); } Area(int width, int height): super(width, height); } main(List<String> args) { // 实例化Size会报错: Abstract classes can't be instantiated // var size = Size(20, 2); var area = Area(10, 2); area.getArea(); print(area.getArea()); } 复制代码
在Dart
中我们使用static
关键字来定义类成员和类方法
main() { var person = Person(); print(person.firstName); person.hide(); print(Person.lastName); Person.show(); } class Person { String firstName = 'top'; // 不能使用this调用静态属性 static String lastName = 'titanjun'; void hide() { print('titanjun'); } // 静态方法 static void show() { print('https://www.$lastName.top'); } } 复制代码
在Dart
中只有单继承, 是不支持多继承的, 但是我们却可以通过其他方式间接实现多继承问题
Dart
中的接口比较特殊, 没有一个专门的关键字来声明接口, 默认情况下所有的类都是隐式接口Dart
开发中,我们通常将用于给别人实现的类声明为抽象类Dart
中通过implements
来实现多继承问题, 但是必须实现这个接口中的所有方法, 而且在方法的实现中不能调用super
方法abstract class Woman { void eat(); void student() { print("student"); } } class Man { void run() { print("runner"); } } class Student implements Woman, Man { @override void eat() { print("eat"); } @override void student() { print("student--student"); } @override void run() { // 这里不能调用super方法 // super.run(); print("run"); } } main(List<String> args) { var stu = Student(); stu.eat(); stu.run(); stu.student(); } 复制代码
implements
实现某个类时,类中所有的方法都必须被重新实现(无论这个类原来是否已经实现过该方法)class
定义类之外,也可以通过mixin
关键字来定义一个类。mixin
定义的类用于被其他类混入使用,通过with
关键字来进行混入mixin Runner { run() { print('在奔跑'); } } mixin Flyer { fly() { print('在飞翔'); } } // 这里可以对原方法不做任何实现 class Bird with Runner, Flyer { } main(List<String> args) { var bird = Bird(); bird.run(); bird.fly(); } 复制代码
欢迎您扫一扫下面的微信公众号,订阅我的博客!