Dart 中的类和对象
- 使用
class关键字声明一个类- 使用
new加上构造函数来创建一个新的对象- 所有对象对继承与
Object类
void main() {
// CXPerson() 默认实现了构造方法
CXPerson p = CXPerson();
// 给属性赋值
p.name = 'chenxi';
p.age = 18;
// 调用 run 方法
p.run();
}
/*
* Dart 中默认会生成 getter 跟 setter 方法
* 属性跟方法都是通过点语法进行访问
* final 修饰的属性必须有初始值,或者在构造方法中 CXPerson(this.nickName) 这样添加也可以
* 没用 final 修饰的属性没初始值的话可以用 ?修饰,代表可以为空
* 在 dart 中方法不可以重载,因为 Dart 中方法名是查找方法的唯一标识
* 可以通过下划线来修饰属性跟方法是否私有,不能被外界访问,但是同一个文件中可以被访问
*/
class CXPerson {
// 属性
String? name;
int? age;
final String nickName = 'cx';
// run 方法
void run() {
print('name:$name age:$age');
}
// Dart 中方法不可以进行重载,及时返回值跟参数不同,
// int run(int a, int b) {
// return a+ b;
// }
// 私有属性跟方法,通过 _ 修饰
String _address = 'beijing';
void _test() {
print('私有方法');
}
}
如上代码中,我们定义了 CXPerson 类,并添加了属性跟方法。
Dart 的构造函数
void main() {
// 实现构造方法,并为属性传值
CXPerson p = CXPerson('chenxi', 'beijing', 20);
CXPerson1 p1 = CXPerson1('cx', 16);
}
class CXPerson {
// 属性
// 使用 final 修饰代表 name 只能被赋值一次,再次修改的话就会报错
final String name;
String _address;
int age = 10;
// 构造方法中通过外部传参的形式为属性赋值
CXPerson(this.name, this._address, int age) {
this.age = age;
}
// 命名构造函数
CXPerson.whithName(this.name, this._address);
// run 方法
void run() {
print('name:$name _address:$_address');
}
}
// 当一个对象所有属性都用 final 修饰的话,这个对象可以被创建为常量对象,使用 const 修饰构造函数
class CXPerson1 {
final String name;
final int age;
// const 修饰构造函数,创建常量对象
const CXPerson1(this.name, this.age);
}
Dart 的工厂构造方法、单例对象、初始化列表
单例构造方法
class FactoryClass {
static FactoryClass? _instance;
// 单例构造方法
// factory FactoryClass() {
// if(_instance == null) {
// _instance = FactoryClass._init();
// }
// return _instance!;
// }
// 简化
// factory FactoryClass() {
// return _instance ??= FactoryClass._init();
// }
// 二次简化
factory FactoryClass() => _instance ??= FactoryClass._init();
// 私有的命名构造函数
FactoryClass._init();
}
初始化列表
class CXPerson {
final String name;
int age = 10;
final double height;
CXPerson(this.name, this.age, double h) :
height = h, assert(h > 0) {
print('name:$name age:$age height:$height');
}
}
初始化列表的目的:
- 给
final属性赋值- 效验传递的值,会先进行效验,效验通过才会执行构造方法
Dart 中的类方法跟对象操作符
静态属性跟静态方法
class StaticClass {
// 静态属性
static int count = 5;
// 实例属性
int currentCount = 10;
// 常量必须用 static 修饰
static const String name = 'chenxi';
// 静态方法
static int sum(int a, int b) {
// 在静态方法中不能访问对象成员变量
// return a + b + this.count;
return a + b;
}
// 实例方法
// 在对象方法中可以访问静态成员变量
int sum1(int a) {
return currentCount + a + count;
}
}
在 Dart 中我们可以为类添加静态属性跟静态方法,这一点跟 swift 很像,但是这里要注意的是在静态方法中不能访问实例属性,这是因为调用静态方法的时候实例可能还没创建,所以不能在静态方法中访问实例属性或者方法。
操作符 “?”
void main() {
var s;
s = StaticClass();
print(s.sum1(10));
// 在这里 s 被赋值为 null,再调用的话就会报给一个空对象发了一个消息的错误,所以可以用 s?.sum1(20) 的方式调用
s = null;
print(s?.sum1(20));
}
class StaticClass {
int sum1(int a) {
return a + 10;
}
}
操作符 “as”
void main() {
var s = Object();
s = StaticClass();
// 这里进行调用的时候需要用 as 进行类型转换
print((s as StaticClass).sum1(10));
}
操作符 “is”
void main() {
var s = Object();
s = StaticClass();
// 通过 is 进行类型判断
if (s is StaticClass) {
print(s.sum1(10));
}
}
操作符 “..”
void main() {
var s = StaticClass();
// 通过 .. 操作符执行完成之后会返回对象本身,所以可以继续调用方法,就是一种链式编程
s..count = 20..sum1(30);
}
class StaticClass {
int count = 10;
int sum1(int a) {
return a + 10;
}
}
Dart 的继承
Dart中使用extends继承一个类- 子类会继承父类中除了自定义构造方法(会继承父类的默认构造方法)跟私有属性以外的所有属性跟方法
Dart是单继承- 父类中如果有一个或多个自定义构造方法,子类必须至少实现其中的一个
void main() {
// Student st = Student();
// 用父类接收子类对象是多态的体现,调用方法的时候需要进行类型判断
Person st = Student();
if (st is Student) {
st.eat();
st.study();
st.name = 'chenxi';
st.age = 17;
print(st.isFree);
}
}
class Student extends Person {
final String schoolName;
study() => print('student study');
// @override 表示复写父类的属性,也可以省略不写,但是为了代码可读性更强,建议加上
@override
bool get isFree => (age??=0) < 18;
@override
eat() => print('student eat');
// 父类中如果有一个或多个自定义构造方法,子类必须至少实现其中的一个,不然会报错
// Student(int? age) : super(age);
//Student() : super.init(); // 显性实现父类中的任意一个自定义构造方法
// 也可以结合初始化列表使用,初始化列表必须放在 super 前面
Student() : schoolName = '北京一中', super.init();
}
class Person {
String? name;
int? age;
double? _height;
// 计算属性
bool get isFree => (_height??=0) < 110;
eat() => print('person eat');
// 父类中如果有一个或多个自定义构造方法,子类必须至少实现其中的一个,不然会报错
Person.init();
Person(this.age);
}
Dart 中的抽象类
- 抽象类不能被实例化,使用 abstract 修饰,有点类似于协议接口。
抽象类的继承 extends
void main() {
AbstractClass as = SubClass();
// 父类是抽象类的话,这里使用多态,就可以直接调用子类的方法而不需要进行类的判断
as.sum(20, 10);
}
// 继续抽象类类似 oc 中继承一个协议,这里继承了一个抽象类就必须要实现抽象类里面的方法
class SubClass extends AbstractClass {
@override
int sum(int a, int b) => a + b;
}
abstract class AbstractClass {
// 这里 sum 没有实现,是一个抽象方法,抽象方法必须放到抽象类里面
int sum(int a, int b);
}
抽象类的继承 implements
void main() {
SubClass as = SubClass();
as.sum(20, 10);
as.sum1(20, 10);
as.sum2(20, 10);
}
// 因为 extends 单继承,如果想继承多个抽象类就要使用 extends
class SubClass implements AbstractClass, AbstractClass1, AbstractClass2, AClass {
@override
int sum(int a, int b) => a + b;
@override
int sum1(int a, int b) => a + b;
@override
int sum2(int a, int b) => a + b;
@override
String? name;
}
abstract class AbstractClass {
int sum(int a, int b);
}
abstract class AbstractClass1 {
int sum1(int a, int b);
}
abstract class AbstractClass2 {
int sum2(int a, int b);
}
class AClass {
String? name;
}
Mixins 混入
- 混入其实就是多继承
- 混入的类不能实现构造方法
- 混入的类不能继承于非 Object 类
- 如果混入的类跟继承的类都实现了某一个方法,那么最后一个混入类的方法会覆盖前面的
void main() {
// 这里 d 可以分别调用 AClass,BClass,CClass 中的方法
DClass d = DClass();
d.a();
d.b();
d.c();
// 如果三个类都有 eat 方法,CClass 会覆盖前面类的 eat 方法,最后会打印 "c eat"
d.eat();
}
class AClass {
a() => print('a............');
eat() => print('a eat');
}
class BClass {
b() => print('b............');
eat() => print('b eat');
}
// 这里需要注意 混入的类不能继承于非 Object 类
// class CClass extends TestClass
class CClass {
// 需要注意 混入的类不能实现构造方法
// CClass();
c() => print('c............');
eat() => print('c eat');
}
class TestClass {}
// 这种写法就是混入,BClass 跟 CClass 称为 DClass 的混入
class DClass extends AClass with BClass, CClass {
}
// 如果 DClass 没有自己的属性跟方法的话也可以像如下这样写
// class DClass = AClass with BClass, CClass;
重载操作符
一般 > 等操作符是用来做值的运算的,如果两个对象想用 > 来比较大小的话,可以在类的内部重载操作符。
void main() {
OperatorClass op1 = OperatorClass(20);
OperatorClass op2 = OperatorClass(10);
print(op1 > op2);
}
class OperatorClass {
int age;
OperatorClass(this.age);
bool operator >(OperatorClass other) => this.age > other.age;
}