Dart是一门使用类和单继承的面向对象语言,有三个基本特征:封装,继承,多态, 所有的类都继承自Ojbect。
类的初始化
-
类的属性需要赋初始值 或 标记延迟初始化 或 作空处理。
-
类的同名方法即默认的构造函数,也可命名构造函数
-
使用final 声明的属性只有getter方法,只读
-
子类重写父类方法,建议@override标记
Class Person extends Object {
int age = 10; //直接初始化
String ? name ; //空处理
late String sex; //延迟初始化
//默认构造函数
Person(this.age, this.name, this.sex);
//命名构造函数
Person.fromJson(Map json){
this.name = json["mame"];
this.age = json["age"];
this.sex = json["sex"];
}
void sayHello() {
print("my age is:" + this.age.toString());
}
}
//调用
var person = Person(10, "zhangsan", "W");
person.sayHello();
获取对象的类型
void main() {
Person p = Person("张三");
print(p.runtimeType);//打印Person
}
属性访问器
每个字段都有一个隐匿的Setter/Getter 方法,可以通过关键字get和set字段重写来扩展功能。(final 或 const 修饰的字段只能有getter 方法)
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
静态成员变量/方法
静态 static 成员对于面向对象而已也是一个非常重要的概念,它和普通成员有着非常大的区别。静态成员由 类 本身直接访问,不依附于 对象。
同样,static也可以修饰静态方法,只能类本身调用。
class Person {
String name;
//静态成员
static String nation = "Chinese";
Person(this.name,this.nation);
//静态方法
static void printNation(){
print("现在朝代是: $nation");
}
void say(){
print("我叫$name,我是$nation人");
}
}
子类继承需要首先实现构造函数
class Woker extends Person {
int salary = 0;
//继承的自定义类需要先实现构造方法
Woker(super.age, super.name, super.sex, this.salary);
@override //标记重写父类方法
void sayHello() {
print("my salary is:" + this.salary.toString());
}
}
级连操作符
.. ?.. 在同一个对象上连续调用多个对象的变量或方法
var person = new Person();
person.name=’Tom’;
Person.age=20;
优化后:
void main() {
var person = Person();
person
..name = 'Tom'
..age = 20
..work();
}
class Person {
String name = '';
int age = 0;
void work() {
print('work...');
}
}
再优化
void main() {
Person()
?..name = 'Tom'
..age = 20
..work();
}
class Person {
String name = '';
int age = 0;
void work() {
print('work...');
}
}
工厂构造函数
并不是任何时候都需要创建一个新的对象,可以返回一个已经缓存好的对象或该类的子类对象。
//待
将类对象作为函数调用
Dart 允许我们将一个类的对象作为函数来调用,只需要实现 call() 函数即可:
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');
}
抽象类
抽象类只负责方法的声明,不负责实现,也不能初始化实例而由子类实现方法 抽象类可以被继承(extends)或 实现(implements).
abstract class Animal {
void haveBaby(); //只有方法名称,没有方法实现
}
class Cat extends Animal {
@override
void haveBaby() {
// TODO: implement haveBaby
}
}
class Monkey extends Animal {
@override
void haveBaby() {
// TODO: implement haveBaby
}
}
类的混合 Mixin
虽然是单继承, 但Dart 可以用with 混合其它多个类的方法
class Eat {
void eat() {
print("eat...");
}
void sayHello() {
print("eat hello");
}
}
class Sleep {
void sleep() {
print("sleep...");
}
void sayHello() {
print("sleep hello");
}
}
注意:
子类在混合其它类的方法时,优先调用自身的方法,其次是混合中的最后一个类,其次是父类
class Woker extends Person with Eat, Sleep {
int salary = 0;
//继承的自定义类需要先实现构造方法
Woker(super.age, super.name, super.sex, this.salary);
void sayHello() {
print("my age is:" + this.age.toString());
}
}
//调用方法
var woker = Woker();
woker.sayHello();
泛型
- 泛型方法
//传入的实参是什么类型,则“T”就代表该类型
T getData<T>(T value) {
return value;
}
//<String>中的String为检验传的参数是否是String类型
print(getData<String>("深圳"));
- 泛型类
//定义泛型类
class ListClass<T> {
List list = new List<T>();
void printInfo() {
for (var i = 0; i < this.list.length; i++) {
print(this.list[i]);
}
}
void add(T value) {
this.list.add(value);
}
}
没有指定类型T的实际类型,因此没有类型校验,传各种类型
main() {
//实例化一个泛型类
ListClass list = ListClass();
list.add(1);
list.add(2);
list.add(3); //添加int类型数据
list.add("深圳"); //添加String类型数据,不会报错
list.printInfo();
指定的类型,在调用其中该泛型类中的方法时会进行类型校验
main() {
//指定了实例化ListClass 类时传入的类型为int类型
ListClass list = new ListClass<int>();
list.add(1);
list.add(2);
list.add(3);
list.add("深圳"); //报错
list.printInfo();
}
- 泛型接口 在具体的类实现了泛型接口后,实例化该类需指定传入的类型:
//抽象类Cache,此处做接口使用
abstract class Cache<T> {
getByKey(String key);
setByKey(String key, T value);
}
//Cache类的实现类
class FileCache<T> implements Cache<T> {
@override
getByKey(String key) {
}
@override
setByKey(String key, T value) {}
}
main() {
//实例化FileCache对象的时候,指定"T"的类型
FileCache fileCache = new FileCache<String>();
fileCache.setByKey("name", "深圳");
//报错,指定setByKey()的第二个参数为String类型,但是这里传入了int类型
fileCache.setByKey("name", 123);
}