Dart 面向对象相关知识点

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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容