Dart是一个现代化的面向对象的程序设计语言,最初的设计其实是想与Javascript进行竞争,让其运行在浏览器中,最早的版本曾经出现过Dart运行在Chrome中的虚拟机,但是,这种做法明显就是割裂互联网,因此也备受争议。但是后来Dart的发展方向发生了变化,Chrome中的Dart虚拟机不用了,而是将Dart语言直接编译为Javascript,页面使用的语言依旧是Javascript,而Dart语言只是作为一个对Web开发的增强型语言。可是再之后Flutter项目的兴起,它直接采用了Dart作为开发语言,又可以通过dart2native将代码编译为在Linux/Windows/macOS平台上可用的二进制代码,至此Dart编程语言成为了目前火热的多端多平台编程语言。
本项目以创建一个成绩查询系统为例,进行展现Dart编程语言的面向对象编程的部分特性,我们以实际项目为驱动逐步介绍Dart语言如何开发一个完整的查询系统。
在Dart语言中,一切皆为对象(除了null之外),你所看到的int,double,bool也都是对象,它不存在原始类型之说,所有的一切类型都继承于Object类。我们可以通过创建新的类型来扩充已有的类型系统。我们将在接下来的教程中创建如下的类,如下表1所示。
类是整个面向对象编程的核心概念。Dart语言中所有的对象都对应一个类(class),类指定了对象的行为和数据。图1定义了一个Student类,第2-5行代码为这个类所定义的数据,它们分别设置了学生的Id值、编号、名称和姓氏4种类别的数据。
第7行代码为Student的构造函数,这种用法看上去像缺少内容似的,但是,它是Dart语言中构造函数的一种简写方式,其对应的完整写法为下图2所示
相比于图2中的代码,图1中采用的简写构造函数更为简洁明了,VS Code编辑器对图2中的写法也给出了代码提示,建议采用图1的写法。
第9-12行代码为Student学生对象作为字符串输出时所对应的内容,这个toString方法为Object类所定义,我们通过重写的方式实现Student的字符串表示,并在第9行代码添加注解@override用以表示Student需要按照自己的方式作为字符串显示。
下图3为表示得分类的定义,通过这个类构建的分数对象保存了一个学生各个学科的成绩值,一共含有5类的学科成绩值,通过第3-7行代码表示,这5个得分值都使用double类型表示得分值。另外还有一个id成员,它表示的是成绩的Id值,最后一个成员studentId表示成绩所对应的学生Id值,通过使用这个studentId值实现学生信息和得分信息的数据关联。
第10-11行代码则为Score类的简写构造函数。第13-16行代码重写了Score类的toString方法,将内容设置为每一个学科所对应的数值。
我们将成绩数据可以存储在内存中也可以存储在文件中,甚至可以将数据存储在数据库中,为了能够实现三种存储方式的统一访问,我们定义了一个接口对象,它提供5种行为,分别是保存数据行为、删除一个数据项行为、更新一个数据项行为、查找一个数据项行为和查找所有数据项行为。但是Dart语言并没有提供接口的关键字,该如何实现呢?可以使用抽象类。如下图4所示的代码。
图4中我们定义了一个Repo抽象类,同时使用了泛型功能,类型T表示存储的数据类型可以按照用户传递的数据类型做进一步的类型化,如果指定T为Score类型,那么存储Repo就可以实现对Score类型的上述5个操作,如果指定T为Student类型,那么存储Repo的操作对象就是Student类。
接下来我们继承自上述的Repo抽象类,创建一个内存得分仓库类MemoryScoreRepo,如下图5所示,图5中我们分别实现了save、remove、update、findOne和findAll共5个方法的重写功能。
学生仓库与得分仓库都继承于Repo泛型类,但是在学生仓库类MemoryStudentRepo的定义中,我们将泛型参数T设置为Student,如图6中第8行代码所示,通过实现Repo类所定义的5个方法,就可以实现对学生对象的增删改查操作,除此之外,学生仓库还提供了另外的一个行为,它支持按照学生编号进行查询学生仓库,因此,又额外的提供了一个接口,通过定义一个抽象类StudentRepo来表示这个额外的行为,图6中第4-6行代码为抽象StudentRepo的定义代码,而第8行代码使用implements关键字表示MemoryStudentRepo需要实现StudentRepo中所定义的方法。
对于类来说,继承机制是单父类继承,即只能指定一个被继承的类,但是实现接口可以指定多个,也就是说我们可以通过指定多个接口(抽象类)让子类实现多个行为。
完成了学生对象类、成绩对象类、学生仓库类、成绩仓库类的创建之后,我们就可以定义业务的接口功能,通过定义一个分数服务类实现,它目前只提供一个方法findScoreByStudentNo,这个方法含有一个表示学生编号的参数studentNo,通过调用这个方法便可以获得此学生对应的各个学科的成绩。
图7中定义了一个ScoreService类,这个类依赖两个对象,分别表示得分仓库和学生仓库对象,在findScoreByStudentNo方法的定义中,第14行代码通过调用学生仓库的findByStudentNo得到对应的学生对象,第19行代码通过调用得分仓库的findOneByStudentId获取到对应的成绩对象。
Dart语言是一个现代化编程语言,在本文中我们使用了面向对象的程序设计方法创建一个成绩查询应用。它提供了类的概念,而且在Dart语言中一切皆为对象;Dart也提供了继承功能,通过继承我们可以实现代码的复用;Dart提供了抽象类功能,通过抽象类功能我们又可以实现接口功能。因此,我们可以说,Dart语言是一个完全支持面向对象编程的语言。