Dart类和对象
类的定义
// Dart中定义一个类 class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } }
Dart中没有private
、public
这些成员访问修饰符类私有的成员 不希望外面访问 在成员变量之前加上 下划线_
变为私有
在Dart中还有一种简化写法 可以自动在构造方法中对成员变量初始化
// Dart 定义一个类 class Person { String name; int age; // 在构造方法中初始化成员变量时 可使用如下写法简化 Person(this.name, this.age); // 如需处理其他变量时 也可单独对其操作 // Person(this.name, this.age, String address){ // print(address); // } // 注意 构造方法不能重载 以上注释掉 }
Dart中没有构造方法的重载 不能写两个同名的构造方法
Getters 和 Setters方法
使用setter和getter方法来操作类的成员变量Dart 所有类中都包含隐式的getter方法 对于非final
修饰的成员 类中还包含隐式的setter方法Dart 可以直接在类外部通过.
操作符访问类成员使得Dart语法更加简洁 不会写出满屏的setXXX、getXXX方法
调用setter和getter方法并不仅仅是为了赋值和访问而是为了一些额外的处理这时候 只需要使用set
与get
关键字实现setter和getter方法即可
class Person { String userName; Person(this.userName); // 方法名前加get关键字 String get name{ return "user:" + this.userName; } // 方法名前加set关键字 set name(String name){ // do something this.userName = name; } } void main() { var p = new Person("zhangsan"); print(p.name); // user:zhangsan p.name = "Jack"; print(p.name); // user:Jack }
创建对象时 new
关键字并不是必须的
写Flutter界面时 不建议写new
关键字实例化对象
因为Flutter框架中没有类似的xml语言来描述UI界面
界面也是使用Dart语言来写
在使用Dart写UI时 要保持代码的简洁和结构化 省略new
会更友好
Dart构造方法
如果没有定义构造方法 则会有一个默认的无参构造方法 且会调用超类的无参构造方法
命名构造方法
Dart类中两个同名构造方法不能重载 但是Dart语言为类新增了一种称为命名构造方法
的东西
class Person { String userName; int age; Person(this.userName, this.age);// 命名构造方法 Person.fromData(Map data) { this.userName = data['name']; this.age = data['age']; } } void main() {// 使用命名构造方法创建对象 var p = new Person.fromData({ "name":"Bob", "age":19 }); print(p.userName); }
注意 使用命名构造方法可以为一个类实现多个构造方法 也可以更清晰的表明意图
常量构造方法
如果想提供一个状态永远不变的对像 在Dart可以创建一个编译时常量对象 节省开销
class ConstPoint { final num x; final num y; // 使用const修构造方法 const ConstPoint(this.x, this.y); // 编译时常量对象 需使用const来创建对象 static final ConstPoint origin = const ConstPoint(0, 0); } void main() { print(ConstPoint.origin.x); print(ConstPoint.origin.y); }
工厂构造方法
当 需要创建一个新的对象或者从缓存中取一个对象时 工厂构造方法就派上了用场
class Logger { final String name; // 创建一个静态Map做为缓存 static final Map<String, Logger> _cache = <String, Logger>{}; // 定义一个命名构造方法 用下划线"_"修饰 将构造方法私有化 Logger._internal(this.name);// 使用关键字factory修饰类同名构造方法 factory Logger(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else {// 调用命名构造方法创建新对象 final logger= new Logger._internal(name); _cache[name] = logger; // 存入缓存 return logger; } } } void main() { var uiLog = new Logger('UI'); var eventLog = new Logger('event'); }
构造方法重定向
有时候一个构造方法会调动类中的其他构造方法来实例化 这时候可以使用构造方法重定向
class Point { num x; num y; // 同名构造方法 Point(this.x, this.y); // 命名构造方法重定向到同名构造方法 中间使用一个冒号 Point.alongXAxis(num x) : this(x, 0); }
类的初始化列表
class Point { final num x; final num y; final num distance; Point(x, y) : x = x, y = y, distance = sqrt(x * x + y * y){ print("这是构造方法"); } } void main() { var p = new Point(2, 3); print(p.distance); }
初始化列表位于构造方法的小括号与大括号之间 在初始化列表之前需添加一个冒号
初始化列表是由逗号分隔的一些赋值语句组成
它适合用来初始化
final
修饰的变量初始化列表的调用是在构造方法之前 也就是在类完成实例化之前 因此初始化列表中是不能访问
this
的
运算符重载
class Point { int x; int y; Point(this.x, this.y); // 使用operator关键字 为该类重载"+"运算符 Point operator +(Point p) { return new Point(this.x + p.x, this.y + p.y); } // 为该类重载"-"运算符 Point operator -(Point p) { return new Point(this.x - p.x, this.y - p.y); } } void main(){ var p1 = new Point(1,5); var p2 = new Point(7,10); // 重载运算符后 类可以使用“+”、“-” 运算符操作 var p3 = p1 + p2; var p4 = p2 - p1; print("${p3.x}, ${p3.y}"); print("${p4.x}, ${p4.y}"); }
打印结果:
8, 15 6, 512
Dart中允许重载的运算符如下:
+ | – | * | ~/ | / | % | ^ |
< | > | <= | >= | == | [] | []= |
& | ~ | << | >> | | |
类的继承
Dart中的继承 使用关键字extends
继承父类 使用关键字super
引用父类
class Father { myFunction(){// do something } } class Son extends Father { @override myFunction(){ super.myFunction(); // do something } }
Dart中的类也只支持单继承但是Dart可以使用一种被称为混入的方式来达到多继承的效果 这需要使用with
关键字
// 首先定义三个父类 class Father1 { a(){ print("this is a func"); } common(){ print("common Father1"); } } class Father2 { b(){ print("this is b func"); } common(){ print("common Father2"); } } class Father3 { c(){ print("this is c func"); } common(){ print("common Father3"); } } //定义子类 class Son extends Father1 with Father2,Father3{} void main() { var obj = new Son(); obj.common(); obj.a(); obj.b(); obj.c(); }
打印结果:
common Father3 this is a func this is b func this is c func1234
也可以直接使用with
等价于如下写法
class Son with Father1,Father2,Father3{}
接口抽象
抽象类
Dart语言没有提供
interface
关键字来定义接口但是Dart语言中保留了抽象类 使用abstract
关键字来修饰抽象类
abstract class Base { // 省略函数体即可定义抽象方法 不需加关键字 func1(); func2(); }
抽象类是不能被实例化的 子类继承抽象类时 必须实现全部抽象方法
隐式接口
实际上在Dart中 每个类都隐式的定义了一个包含所有实例成员的接口 并且该类实现了这个接口
因此 如果 想实现某个接口 但有又不想继承 则可以使用这种隐式接口机制
需要用到关键字implements
class People { void greet(){ print("Hello"); } } class Student implements People{ @override void greet(){ print("Hi,I'm Alice."); } } greet(People p){ p.greet(); } void main() { greet(new Student()); }
尊贵的董事大人
英文标题不为空时 视为本栏投稿
需要关键字 描述 英文标题