Dart语言学习(十二) Dart面向对象
Dart作为一种高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式。
基于mixin的继承方式是指:一个类可以继承自多个父类,相当于其他语言里的多继承。
所有的类都有同一个基类Object,这和特性类似于Java、Objective-C 等语言,Java所有的类也都是继承自Object,也就是说一切皆对象。
- //实例化了一个User类的对象user
- var user = new User('Liming',25);
实例化成员变量
- Class User{
- String name;//name 成员变量
- int age;//age 成员变量
- }
类定义中所有的变量都会隐式的定义setter方法,针对非空的变量会额外增加getter方法。
实例化成员变量请参考如下代码:
- void main(){
- var user = new User();
- user.name = 'Liming';//相当于使用了name的setter方法
- user.age = 25;
- }
构造函数
1.常规的构造函数
构造函数是用来构造当前类的函数,是一种特殊的函数,函数名称必须要和类名相同才行.
如下代码为User类添加了一个构造函数,函数里给User类的两个成员变量初始化了值:
- Class User{
- String name;
- int age;
- User(String mName,int mAge){
- this.name = mAge;
- this.age = mAge;
- }
- }
this关键字指向了当前类的实例
上面的代码可以简化为:
- Class User{
- String name;
- int age;
- User(this.name,this.age);
- }
第一种没有简化的构造方法初始化成员变量是在方法体内进行初始化的,
第二种简化的构造方法初始化成员变量,是在实例化类的时候直接进行赋值初始化的。
2.命名的构造函数
使用命名构造函数是 从另一类或现有的数据中快速实现构造函数 ,代码如下所示:
- Class User{
- String name;
- int age;
- //普通构造函数
- User(this.name,this.age);
- //命名构造函数
- User.fromJson(Map json){
- name = json['name'];
- age = json['age'];
- }
- }
- //在实例化类的时候,如果没有传参,会默认调用无参数的构造方法
- //普通构造函数
- var user = new User('张三',25);
- //命名构造函数
- var user = new User.fromJson(mMapJson);
3.子类的创建
注1:子类在继承父类的时候,如果在父类中有显示的提供一个无名、无参的构造函数,不会继承父类无名有参构造函数和命名构造函数,即:子类只会继承父类无名无参的构造函数。(程序会给类隐式的生成一个无名、无参的构造函数)
注2:子类在继承父类的时候,如果在父类中没有有显示的提供一个无名、无参的构造函数,子类必须手动调用父类的一个构造函数,在这种情况下,调用的父类的构造函数要放在子类构造函数之后,在子类构造函数体之前,用“:”分隔。
注3:父类的构造函数会在子类的构造函数前调用。
注4:默认情况下,子类只能调用父类无名、无参数的构造函数。
注1和注3:父类中有一个无名、无参的构造函数,子类继承父类,会默认继承父类无名、无参的构造函数(即使有其他无名、有参的构造函数或者命名构造函数,子类都不会调用),并且,父类的无名、无参的构造函数会在子类的构造函数之前被调用。
- Class Futher {
- //无名、无参的构造函数
- Futher(){
- print('我是父类无名、无参的构造函数');
- }
- }
- Class Son extends Futher {
- //因为父类有显式的声明一个无名、无参的构造函数,所以不用手动调用父类的构造函数。
- Son.fromJson(Map mMapJson){
- print('我是子类的命名构造函数');
- }
- }
- var son = new Son.fromJson(mMapJson);
- //打印结果
- //我是父类无名、无参的构造函数
- //我是子类的命名构造函
注2:下面代码里,子类的命名构造方法写了两种方式,第一种是正确的,第二种是错误的,有详细的注释, 如果有疑问请留言。
- Class Futher {
- //无名、无参的构造函数
- Futher.printSth(){
- print('我是父类无名、无参的构造函数');
- }
- }
- Class Son extends Futher {
- //因为父类没有有显式的声明一个无名、无参的构造函数,所以需要手动的调用父类的构造函数。
- Son.fromJson(Map mMapJson) : super Futher.printSth{
- print('我是子类的命名构造函数');
- }
- //这种写法会报错,因为父类中没有显示的提供一个无名、无参的构造函数。所以需要像上面那样,手动调用父类的一个构造函数
- Son.fromJson(Map mMapJson){
- print('我是子类的命名构造函数');
- }
- }
4.构造函数初始化列表
上面在讲解常规的构造函数和命名构造函数的时候,示例代码都有对类中的成员变量进行了初始化,
特点是在构造函数的方法体内进行初始化,初始化成员变量还有另一种方式,就是在构造函数运行前来初始化成员变量。
- Class User {
- String name;
- int age;
- User(mName,mAge)
- :name = mName,
- age = mAge{
- // Do Some Thing
- }
- }
特点是在构造函数的方法体前(大括号前面)来初始化成员变量,变量间用“,”分隔。
读取和写入对象
get()和set()方法是专门用于读取和写入对象的属性的方法,每一个类的实例,系统都会隐式的包含有get()和set()方法。
例如,定义一个矩形的类,有上、下、左、右:top、bottom、left、right四个成员变量,使用get及set关键字分别对right、bottom进行获取和设置值。代码如下所示:
- Class Rectangle {
- num left;
- num top;
- num width;
- num height;
- Rectangle(this.left,this.top,this.width,this.height);
- num get right => left + width;//获取righht的值(第一行)
- set right(num value) => left = value - width;//设置right的值,同时left也发生了变化(第二行)
- num get bottom => top + height;//获取bottom的值(第三行)
- set bottom(num value) => top = value - height;//设置bottom值,同时top也发生了变化(第四行)
- }
- void main(){
- var rect = new Rectangle(3,4,20,15);//实例化Rectangle,并给类中的4个变量进行初始化赋值
- print('left:'+rect.left.toString());//获取left的值,并打印 left = 3
- print('right:'+rect.right.toString());//获取right的值,并打印,这里执行了Rectangle类中第一行代码,right = left + width,right = 3+20 = 23
- rect.right = 30;//重新给right进行赋值 right = 30,这里执行了Rectabgke类中的第二行代码,将right的值设置为30,并且,将left的值改为30 - 20,left = 30-20 = 10
- print('right的值改为30');
- print('left:'+rect.left.toString());//获取left的值,并打印,因为上面给right重新赋值的时候,也改变了left的值,所以,此时left = 10
- print('right:'+rect.right.toString());//rect.right = 30将right的值改为了30,所以,right = 30
- print('top:'+rect.top.toString());
- print('bottom:'+rect.bottom.toString());
- rect.bottom = 50;
- print('bottom的值改为50');
- print('top:'+rect.top.toString());
- print('bottom:'+rect.bottom.toString());
- }
- //打印结果
- left:3
- right:23
- right的值改为30
- left:10
- right:30
- top:4
- bottom:19
- bottom的值改为50
- top:35
- bottom:50
上面的示例注释已经解释的很清楚了,如果有任何疑问,请留言!!!
这里我就解释一下“=>”的作用,在Dart里面,大家可以简单的理解为接下来要继续执行后面的操作。
重运算符载操作
在讲解重载运算符前需要先说明Dart里面的一个关键字operator,operator和运算符一起使用,表示一个运算符重载函数,在理解时可以将operator和运算符(如operator+或operator-)视为一个函数名。编写一个例子方便理解。
- Class Vector {
- final int x;
- final int y;
- const Vector(this.x,this.y);
- //重载加号 + (a+b)
- Vector operator + (Vector v){
- return new Vector(x + v.x,y + v.y);
- }
- }
- void main() {
- //实例化两个变量
- final result1 = new Vector(10,20);
- final result2 = new Vector(30,40);
- final result = result1 + result2;
- print('result.x = '+result.x.toString()+'',+'result.y = '+result.y.toString());
- //打印结果
- result.x = 40,result.y = 60
- }
首先创建了一个Vector类,声明两个成员变量x和y还有一个构造方法,在Vector类里面重载一个加法运算符,重载操作返回Vector对象,接下来在main函数里面,实例化了两个Vector变量,两次操作分别给
x和y进行了赋值,x = 10;y = 20;x = 30;y = 40。然后让result1和result2这两个变量相加,看到这里大家可能会有疑问,两个对象变量怎么相加呢?这里我们的运算符重载就发挥出作用了,实际上,在执行final result = result1 + result2;这行代码的时候,其实是对象result1调用了"operator +"这个函数,并将result2这个对象当作一个参数传递给了这个函数,从而实现了对象result1中的x和对象result2中的x相加,对象result1中的y和对象result2中的y相加的操作,所以最终打印的结果result.x = 40,result.y = 60。
注:对于 Dart 提供的所有操作符,通常只支持对于基本数据类型和标准库中提供的类的操作,而对于用户自己定义的类,如果想要通过该操作符实现一些基本操作(比如比较大小,判断是否相等),就需要用户自己来定义关于这个操作符的具体实现了。
继承类
继承是面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象具有父类的实例域和方法;或子类从父类继承方法,使得子类具有父类相同的行为。Dart里面使用extends关键字来实现继承,super关键字来指定父类。
- Class Animal {
- void eat(){
- print('动物会吃');
- }
- void run(){
- print('动物会跑');
- }
- }
- Class Human extends Animal {
- void say(){
- print('人会说');
- }
- void study(){
- print('人会学习');
- }
- }
- void main(){
- var animal = new Animal();
- animal.eat();
- animal.run();
- value human = new Human();
- human.eat();
- human.run();
- human.say();
- human.study();
- //打印结果
- 动物会吃
- 动物会跑
- 动物会吃
- 动物会跑
- 人会说
- 人会学习
- }
抽象类
抽象类类似于Java语言中的接口。抽象类里不具体实现方法,只是写好定义接口,具体实现留着调用的人去实现。抽象类可以使用abstract关键字定义类。
- 抽象类通过abstract关键字来定义。
- Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们成为抽象方法。
- 如果子类继承了抽象类,就必须实现里面的抽象方法。
- 如果把抽象类当作接口实现的话,就必须得实现抽象类里面的所有属性和方法。
- 抽象类不能实例化,只有继承它的子类可以实例化。
- abstract class Animal{
- eat(); //抽象方法
- run(); //抽象方法
- printInfo(){
- print('我是一个抽象类里面的普通方法');
- }
- }
- class Dog extends Animal{
- @override
- eat() {
- print('小狗在吃骨头');
- }
- @override
- run() {
- // TODO: implement run
- print('小狗在跑');
- }
- }
- class Cat extends Animal{
- @override
- eat() {
- // TODO: implement eat
- print('小猫在吃老鼠');
- }
- @override
- run() {
- // TODO: implement run
- print('小猫在跑');
- }
- }
- void main(){
- Dog d=new Dog();
- d.eat();
- d.printInfo();
- Cat c=new Cat();
- c.eat();
- c.printInfo();
- // Animal a=new Animal(); //抽象类没法直接被实例化
- }
Dart语言学习(十二) Dart面向对象的更多相关文章
- Dart语言学习(十五) Dart函数方法
Dart函数方法可分为两类: 一.内置方法/函数: print(); 二.自定义方法: 自定义方法的基本格式: 返回类型 方法名称(参数1,参数2,...){ 方法体 return 返回值; } vo ...
- Dart语言学习(十四) Dart泛型
什么是泛型? 通俗理解:泛型就是解决 类 接口 方法的复用性.以及对不特定数据类型的支持(类型校验) 如下代码,只能返回string类型的数据 String getData(String value) ...
- Dart语言学习(十) Dart流程控制语句
一.条件语句:if.if...elseif.if...elseif...else int score = 95; if (score >=90) { print('优秀'); } else if ...
- C语言第十二讲,文件操作.
C语言第十二讲,文件操作. 一丶文件操作概述 在操作系统中,我们的文档都称为文件.操作系统也为我们提供了接口进行操作.不同语言都是使用的相同的接口,只不过封装的上层接口不一样 操作文件的步骤 打开文件 ...
- Go语言学习笔记二: 变量
Go语言学习笔记二: 变量 今天又学了一招如何查看go的版本的命令:go version.另外上一个笔记中的代码还可以使用go run hello.go来运行,只是这种方式不会生成exe文件. 定义变 ...
- (转)SpringMVC学习(十二)——SpringMVC中的拦截器
http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...
- Fluter基础巩固之Dart语言详解<二>
继续学习枯燥的Dart语言语法,目前的耐得住寂寞是为了将来学得“爽”做准备的!!! 异常: Dart 提供了 Exception 和 Error 类型, 以及一些子类型.还可以定义自己的异常类型.但是 ...
- Dart语言学习(七)Dart Map类型
映射(Maps)是无序的键值对: 常用属性: keys 获取所有的key值 values 获取所有的value值 isEmpty 是否为空 isNotEmpty 是否不为空 常用方法: remove( ...
- GO语言学习(二)Windows 平台下 LiteIDE 的安装和使用
1. 安装 Go 语言并设置环境变量 参考GO语言学习(一) 2. MinGW 的下载和安装 Windows 下的 Go 调试还需要安装 MinGW. 2.1 下载安装工具的安装 最新版本下载安装工具 ...
随机推荐
- HBase 分裂(split)
1. 为什么split 最初一个Table 只有一个region(因此只能存放在一个region server上).随着数据的不断写入,HRegion越来越大,当到达一定程度后分裂为两个,通过负载均衡 ...
- JMM&Thread
1.概述 高效并发通过JAVA线程之间提高并发协调实现,在实现过程中需考虑硬件的效率和一致性,但在运算的过程中需要考虑处理器与内存的交互,所以基于高速缓存的存储交互解决的处理器与内存的方案,在对多处理 ...
- 深入ThreadLocal的底层实现机制以及对应的使用风险
学习Java中常用的开源框架,Mybatis.Hibernate中线程通过数据库连接对象Connection,对其数据进行操作,都会使用ThreadLocal类来保证Java多线程程序访问和数据库数据 ...
- 20191114-2 Beta阶段事后诸葛亮会议
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/10005 组长组“多彩夕阳”项目beta阶段诸葛亮会议 设想和目标 1.我 ...
- TVP访谈 | 贝壳金服史海峰:中台虽百家争鸣,但不是所有企业必需品
导语 | 中台作为一个技术概念,曾一度被捧得火热.那么,中台现在发展到了什么阶段呢?对于所有企业来讲,中台都是普适的么?中台在具体的落地过程中,究竟存在哪些问题呢?腾讯云最具价值专家(TVP)史海峰, ...
- $Noip2016/Luogu2827$蚯蚓
$Luogu$ $Sol$ 乍一看就是个模拟叭,用个优先队列维护不就好了.不过这里有一个问题就是怎么解决没被切的蚯蚓的增长问题.可以这样处理,每次切一条蚯蚓,给切完之后的都减去$q$,最后输出答案时都 ...
- 微信小程序开发笔记(二)
一.前言 继承上一篇所说的,有了对微信小程序的基础概念后,这边将会示范动手做一个小程序,在动手的过程中我们可以更快的熟悉小程序里面的架构和开发流程. 二.小程序的设计 这次要做的是一个猜数字的程序,程 ...
- 快速部署postfix邮件服务器
• 装包.配置.起服务– 默认的标准配置即可为本机提供发/收邮件服务– 若有必要,可扩大服务范围(邮件域) 前提:邮件服务器,必须为手工配置永久主机名虚拟机server0[root@server0 ~ ...
- Don’t Repeat Yourself,Repeat Yourself
Don't Repeat Yourself,Repeat Yourself Don't repeat yourself (DRY, or sometimes do not repeat yoursel ...
- 单用户登陆demo-后者挤到前者,类似QQ
单用户登陆demo ,采用的是Tp5. 流程是,当用户首次登陆是验证用户帐号密码,成功的,用当前时间戳加上用户id和ip 拼接成一个标识,暂且sign ,然后存入cookie ,时间戳存入缓存redi ...