Dart面向对象

1,437 阅读6分钟

前言

前文Dart基础语法介绍了Dart的基础语法,本文主要介绍Dart的面向对象的特性。废话不多说,我们开始吧。

准备

  • 使用终端创建Flutter项目。

image.png

  • 将工程目录拖入Android Studio,删除mian函数以为的所有代码。

image.png

下面我们就用这个项目来探究下Dart的面向对象的特性。

一: 类与对象

  • Object类是所有非nullDart对象的基类。因为Object类是非空的Dart类的根类,所有非空的Dart类都是Object类的子类。

  • Dart中使用class关键字声明一个类。使用new跟上构造函数创建对象,new可省略。

  • Dart类定义属性需要给定初始值,或者在构造函数给定初始值,否则需要使用var或类型加上?(如String?)来定义(即告诉编译器此属性可为空)。

  • Dart的属性默认会生成gettersetter方法;但final修饰的属性必须指定初始值,且只会生成getter方法(不会生成setter方法,即不可修改)。属性和方法都通过.语法访问。

  • Dart中方法的名称是寻找方法的唯一标识,所以方法不能重载。

image.png


  • Dart的类使用_声明私有属性和私有方法。同一文件中多个类的属性和方法,可以互相访问,不论公有还是私有。

image.png

二: 构造函数

  • 定义一个类之后,它就会有默认的构造函数,默认构造函数没有参数。自定义构造函数后,默认构造函数就会失效。

image.png

  • 构造函数形参名和属性名相同,会导致赋值不成功。

image.png

  • Dart构造函数语法糖,直接在参数列表里,用this.属性代替形参,这样就会自动赋值相应属性了,赋值相关代码可省略。且相关属性即使不给初始值,类型也可以不用添加?。当然final修饰的属性,初始化之后依然不可更改。

image.png

未添加?的属性和final修饰的属性,未指定初始值的时候,一定要在语法糖构造函数里赋值。

  • Dart还可以定义命名构造方法。

image.png

  • 当一个类的所有属性都是final修饰时,那么这个类的对象可以被创建为常量对象,使用const修饰构造函数。

image.png

  • 如果初始化某个对象时,因为未导入相应文件报错,可以选中相应类名,然后option + 回车键,就会出现相应提示,选中导入相应文件即可。

image.png

三: 工厂构造 & 单例对象 & 初始化列表

3.1 工厂构造 & 单例对象

  • 常量对象不是单例对象。

image.png

  • Dart使用static声明单例对象,使用factory修饰的工厂构造函数创建单例对象。

image.png

3.2 初始化列表

  • 构造函数可以在形参的()后面用:指定初始化列表。初始化列表在构造函数之前执行。初始化列表的作用:
    • 可以给属性赋值。主要指final修饰的属性。
    • 校验构造函数传入的值。不符合条件会报错。 image.png

image.png

初始化列表里不可以使用this

四: 静态方法和对象操作符

4.1 静态属性 & 静态方法

  • Dart的类方法其实就是静态方法。除了静态方法外,还有静态属性,都使用static修饰。静态属性和静态方法,直接使用类来调用。

image.png

  • 静态方法里不可以访问实例属性。因为还没有实例,所以访问不了。

image.png

  • 实例方法可以访问静态属性。

image.png

  • 静态属性在内存中只有一份。

image.png

  • 只有静态属性才能被声明为常量。

image.png

4.2 对象操作符

  • var声明的对象,如果为null,调用实例方法会报错,调用方法时,在对象后面加上?,可以避免这种情况。

image.png

  • Dart对象可以使用as进行强制类型转换,使用is进行类型判断。

image.png

  • Dart对象可以使用..来进行链式编程。注意:..链式编程每步返回的都是对象本身,而不是操作的结果。

image.png

五: Dart的继承

  • Dart使用关键字extends来进行继承,省略的情况下默认是继承Object类。子类会继承父类除了构造方法以外的属性和方法,Dart的继承属于单继承。

image.png

  • 子类重写父类计算属性和方法需要使用@overrideDart同样支持多态。

image.png

  • 子类默认构造函数会调用父类默认构造函数。非默认构造函数需要使用super调用。注意:当父类有一个或多个非默认构造函数时,子类必须显示使用super进行调用。

image.png

image.png

  • 构造方法里显示调用super必须放在初始化列表的最后面。

image.png

六: Dart的抽象类和接口

  • 抽象类是不能被实例化的类,使用abstract修饰。抽象类里的方法没有实现,被称为抽象方法。

image.png

  • 子类必须实现抽象类的抽象方法。这样抽象类就可以多态实例化子类,调用相关抽象方法,而不需要判断是否是相关子类。

image.png

  • 抽象类有点类似OC中的Protocol,通过implements我们可以实现多个抽象类。当然同时也必须实现抽象类的抽象方法。

image.png

  • implements不仅可以实现抽象类,还可以实现普通类,并需要实现普通类的所有实例属性和实例方法。不过一般不会这样使用。

image.png

七: Mixins混入

  • Dart可以使用Mixins(混入)实现多继承。使用组合关键字extends ... with ...来指明继承和混入的类。

image.png

  • 如果多继承的类里有同名方法,最后一个继承的类会覆盖前面的。

image.png

  • Mixins也有其局限性,当一个类拥有构造函数时,不可以作为混入类。

image.png

  • 当一个类继承非Object类时,也不要作为混入类。

    • 如果被继承的非Object类没有或只有默认构造函数,编译器会报错,但是可以运行。

    image.png

    • 如果有非默认构造函数,编译和运行都会报错。

    image.png

  • 当一个类本身没有任何实现,只是继承、混入了其他类的时候,可以直接写成下面的形式:

// class ClassD extends ClassA with ClassB, ClassC {}
class ClassD = ClassA with ClassB, ClassC;

八: 运算符重载

  • Dart可以根据自己的需要对运算符进行重载。

image.png

九: 总结

本文的内容到这里就结束了,还有很多相关知识,后续遇到再记录。期待大家的持续关注。