Dart做为一种高级语言,支持面向对象的不少特性,而且支持基于mixin的继承方式。html
基于mixin的继承方式是指:一个类能够继承自多个父类,至关于其余语言里的多继承。编程
全部的类都有同一个基类Object,这和特性相似于Java、Objective-C 等语言,Java全部的类也都是继承自Object,也就是说一切皆对象。json
//实例化了一个User类的对象user var user = new User('Liming',25);
Class User{ String name;//name 成员变量 int age;//age 成员变量 }
类定义中全部的变量都会隐式的定义setter方法,针对非空的变量会额外增长getter方法。ide
实例化成员变量请参考以下代码:函数
void main(){ var user = new User(); user.name = 'Liming';//至关于使用了name的setter方法 user.age = 25; }
构造函数是用来构造当前类的函数,是一种特殊的函数,函数名称必需要和类名相同才行.学习
以下代码为User类添加了一个构造函数,函数里给User类的两个成员变量初始化了值:this
Class User{ String name; int age; User(String mName,int mAge){ this.name = mAge; this.age = mAge; } }
this关键字指向了当前类的实例spa
上面的代码能够简化为:code
Class User{ String name; int age; User(this.name,this.age); }
第一种没有简化的构造方法初始化成员变量是在方法体内进行初始化的,htm
第二种简化的构造方法初始化成员变量,是在实例化类的时候直接进行赋值初始化的。
使用命名构造函数是 从另外一类或现有的数据中快速实现构造函数 ,代码以下所示:
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);
注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('我是子类的命名构造函数'); } }
上面在讲解常规的构造函数和命名构造函数的时候,示例代码都有对类中的成员变量进行了初始化,
特色是在构造函数的方法体内进行初始化,初始化成员变量还有另外一种方式,就是在构造函数运行前来初始化成员变量。
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 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学习系列文章:https://www.cnblogs.com/jukaiit/category/1636484.html