目录
前言
构造函数
属性和方法私有化
Getter与Setter
类的初始化列表
对象操作符
继承
抽象类和接口
mixins
总结
前言
Dart是一门面向对象语言,满足面向对象编程(OOP)的三个基本特征:封装、继承、多态。Dart是单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类。Dart类和对象的概念同Java很像,快速浏览了一遍Dart关于类和对象的概念,在此仅记录一下Dart类和对象与Java的区别。其他基本的概念就不过多赘述。
构造函数
首先来谈谈Dart类与java类构造函数的区别。
区别一:Dart类中有默认无参的构造函数,但是一旦提供了有参的构造函数之后,无参构造函数则不能使用。如下代码中,Person类中提供了带参数的构造函数,则直接使用new Person()代码来初始化对象时不能通过编译。
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
void main() {
Person p1 = new Person(); //报错
Person p2 = new Person("Angus", 18); //有效
}
区别二:构造函数简写 ,上面Person类的带参构造函数在Dart中提供了一种简写的方法。比如:
class Person {
String name;
int age;
Person(this.name, this.age);
}
区别三:Dart中多个构造函数不能同名,为了能够写多个构造函数,Dart中提供了命名构造函数的概念,使用方法是在类名后加.otherName。比如如下代码演示了命名构造函数的使用。
class Person {
String name;
int age;
Person(this.name);//两个同名,后者报错
Person(this.name, this.age);//两个同名,后者报错
Person.info(this.name);//命名构造函数
}
void main() {
Person p = new Person.info("Angus"); //使用命名构造函数初始化对象
}
属性和方法私有化
Dart和Java不一样,Data中没有 public private protected这些访问修饰符号,但是我们可以使用“_”把一个属性或者方法定义成私有。使用私有化有一个前提,是类必须单独一个文件,使用类的方法不能同类在同一个文件下。比如:
class Person {
String name;
int _age;
Person(this.name, this._age);
}
void main() {
Person p = new Person("Angus",18);
print(p.name);//Angus
print(p._age);
}
上面代码Person和main方法在同一个文件,可以访问到_age这个私有变量。
class Person {
String name;
int _age;
Person(this.name, this._age);
void _printAge() {
print(this._age);
}
void printPerson() {
_printAge();
print("${this.name}---${this._age}");
}
}
上面代码中,将Person类单独放在一个文件,并定义了私有变量_age和私有方法_printAge()。
import 'lib/Person.dart';
void main() {
Person p = new Person("Angus",18);
print(p.name);//Angus
p.printPerson();//Angus---18
print(p._age);//报错
p._printAge();//报错
}
通过上面的方式使用Person类,会发现没法直接访问私有变量_age和私有方法_printAge()。
Getter与Setter
Dart中定义Getter与Setter方法有单独的关键字get和set,通过这两个关键字来修饰的方法,访问方法同普通方法不一样,访问Getter与Setter方法同访问公共变量一致。
class Animal {
int age;
String _name;
int get getAge => age;
set setAge(int age) {
this.age = age;
}
String get name => _name;
set name(String value) {
_name = value;
}
}
如上代码中分别为age和_name提供了Getter与Setter方法,注意前面的关键字get和set。
import 'lib/Animal.dart';
void main() {
Animal animal = new Animal();
animal.setAge = 18;
print(animal.getAge);//18
animal.name = "熊猫";
print(animal.name);//熊猫
}
如上代码演示如何访问Getter与Setter方法,访问时后面没有括号,而是当作公共变量一样来访问。
类的初始化列表
Dart中我们也可以在构造函数体运行之前初始化实例变量,方式是在构造函数后面加“:”然后分别为变量赋值。比如:
class Rect{
int height;
int width;
Rect():height=2,width=10{
print("${this.height}---${this.width}");
}
getArea(){
return this.height*this.width;
}
}
void main(){
Rect r=new Rect();//2---10
print(r.getArea()); //20
}
对象操作符
Dart中提供了一些不一样的对象操作符:
? 条件运算符 ,判断对象是否为空,为空时阻住后面的代码执行,比如:
main() {
Person p;
p?.printInfo(); //不会报错,也没有打印
Person p2 = new Person('张三', 20);
p2?.printInfo();//张三---20
}
as 类型转换
main() {
Object p1=new Person('张三1', 20);
p1.printInfo();//报错
(p1 as Person).printInfo();//张三1---20
}
is 类型判断
main() {
Person p=new Person('张三', 20);
if(p is Person){
p.name="李四";
}
p.printInfo();//李四---20
print(p is Object);//true
}
.. 级联操作 (连缀),通过这个操作符可以实现链式访问。
main() {
Person p1=new Person('张三1', 20);
p1.printInfo();//张三1---20
p1..name="李四"
..age=30
..printInfo();//李四---30
}
继承
Dart中的类的继承:
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法 getter和setter
Dart中继承同java继承的区别在于构造方法重写时给父类构造方法传参,代码如下:
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);//复写父类的构造方法并传参
run(){
print('run');
super.work(); //子类调用父类的方法
}
//覆写父类的方法
@override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
}
抽象类和接口
Dart中抽象类定义和使用基本同Java一样,区别在于Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。比如:
abstract class Animal{
eat(); //抽象方法
run(); //抽象方法
printInfo(){
print('我是一个抽象类里面的普通方法');
}
}
和Java一样,dart也有接口,但是和Java还是有区别的。首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。同样使用implements关键字进行实现。但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类,建议使用抽象类定义接口。
extends抽象类和implements的区别:
1、如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
abstract class Animal{
eat();
run();
}
class Dog implements Animal{
@override
eat() {
print('小狗在吃骨头');
}
@override
run() {
print('小狗在跑');
}
}
Dart中一个类同样可以实现多个接口
abstract class A{
String name;
printA();
}
abstract class B{
printB();
}
class C implements A,B{
@override
String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
mixins
Dart新增了一个mixins的概念,mixins的中文意思是混入,就是在类中混入其他功能,在Dart中可以使用mixins实现类似多继承的功能。
因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:
1、作为mixins的类只能继承自Object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性
class Person{
String name;
num age;
Person(this.name,this.age);
printInfo(){
print('${this.name}----${this.age}');
}
void run(){
print("Person Run");
}
}
class A {
String info="this is A";
void printA(){
print("A");
}
void run(){
print("A Run");
}
}
class B {
void printB(){
print("B");
}
void run(){
print("B Run");
}
}
class C extends Person with B,A{
C(String name, num age) : super(name, age);
}
void main(){
var c=new C('张三',20);
c.printInfo();//张三----20
c.printB();//B
print(c.info);//this is A
c.run();//A Run
}
如上代码演示了mixins的使用,通过with关键字来使用mixins。需要注意的是,当C类中继承的Person类、A类和B类中有同名方法和属性时,总是后面的覆盖前面的。比如c.run()执行的是最后A类的run方法。
mixins的实例类型是什么?很简单,mixins的类型就是其超类的子类型。
void main(){
var c=new C();
print(c is C); //true
print(c is A); //true
print(c is B); //true
}
总结
Dart是一门真正的面向对象语言,我觉得它综合和ES6和Java的特点,分别取了各自的长处,摒弃了各自的短处。学习起来也非常简单,很容易入门。