dart总结(三.类,继承,多态,静态,枚举,mixins和隐式接口详解)

Object

Dart中所有的东西都是对象,所有的对象都继承自Object类.

普通类的声明

特点:用new关键字实例化

  class Class01{
    //变量
    int a;
    String b;
    var c=3;
    //函数
    void fun01(int d){
    }
    String fun2(){
      return b;
    }
  }
void main(){
//记住练习类要在main函数外面创建,里面会报错
  var class01= new Class01();
  print(class01.c);//3
  class01..a=1..b="b";//..级联操作符可以连续调用类的属性进行赋值
  print(class01.a);//1
  print(class01.b);//'b'
}

默认构造函数

class Class02{
  //变量
  int a =3;
  //未声明构造函数,有下面默认构造函数
  Class2(){}
}

void main (){
 var class02=new Class02();//正常实例化
 print(class02.a);//3
}

自定义构造函数

class Class03{
  int a;
  String b;
  // 自定义构造函数
  Class03(int a,String b){
    this.a=a;
    this.b=b;
  }
}

void main (){
 var class03=new Class03(1, "a");
 print(class03.a);//1
 print(class03.b);//a
}

上面简写

class Class03{
  int a;
  String b;
  // 自定义构造函数简写
  Class03(this.a,this.b);
}
void main (){
  var class03 =new Class03(1, "a");
  print(class03.a);//1
 print(class03.b);//a
}

命名构造函数

其实就是一种可以为类声明多个不同的构造函数.

class Class03{
  int a;
  String b;
  Class03(int a,String b){
    this.a=a;
    this.b=b;
  }
  Class03.fun1(int a){
    this.a=a;
  }
  Class03.fun2(String b){
    this.b=b;
  }
}

void main (){
  var class03=new Class03(4, "d");
  var class04=new Class03.fun1(5);
  var class05=new Class03.fun2('d');
  print(class04.a);//5
  print(class05.b);//'d'
}

静态构造函数

特点:对象和里面的变量都不会改变,用final关键字修饰变量,用const修饰构造函数,实例化使用的是const关键字,而不是new关键字.

class Class04{
  // 用final修饰常量
  final int a;
  final String b;
  // 用const 修饰构造函数
  const Class04(this.a,this.b);
  //普通函数
  void fun01(){
    print("aa");
  }
}

void main (){
  var class04=const Class04(1, "a");
  print(class04.a);//1
  class04.fun01();//aa
}

重定向构造函数

class Class05{
  int a;
  String b;
  Class05(int a,String b){
    this.a=a;
    this.b=b;
  }
  Class05.fun1(int a){
    this.a=a;
  }
  // 重定向构造函数
  Class05.fun2(String b):this.fun1(33);//重定向到函数fun1
  Class05.fun3(String b):this(33,"ccc");//重定向到构造函数Class05
}

void main (){
 var class05 =new Class05(55, "fff");
 print(class05.a);//55
 var class06=new Class05.fun2("hhh");
 print(class06.a);//33,被重定向到了fun1
 var class07=new Class05.fun3("hhh");
 print(class07.a);//33,被重定向到了构造函数Class05
 print(class07.b);//ccc,被重定向到了构造函数Class05

工厂构造函数

特点:

class Class06 {
  int a;
  static Class06 instance;//这里用static关键字创建一个单例
  factory Class06(int a){//这里的构造函数用factory修饰,使用new时,不再是创建一个全新的实例了,而是通过函数体内return获取到实例
    if(instance==null){
      instance=new Class06.fun1(a);
    }
    return instance;
  }
  Class06.fun1(this.a);//这里是实例化当前对象的构造方法
}

void main (){
var class06=new Class06(22);
print(class06.a);//22
}

get 和 set 修饰词的应用

class Rect{
  num height;
  num width; 
  
  Rect(this.height,this.width);
  get area{//注意get这里是类
    return this.height*this.width;
  }
  set areaHeight(value){//set是设置方法
    this.height=value;
  }
}

void main(){
  Rect r=new Rect(10,4);
  print("面积:${r.area}");  //10*4=40,所以输出40.注意调用直接通过访问属性的方式访问area,如果调用括号会报错
  r.areaHeight=6;//注意设置也是直接通过实例.方法名的方式设置

  print(r.area);//输出24

}

抽象方法

特点:

  • 1、抽象类通过abstract 关键字来定义

  • 2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。

  • 3、如果子类继承抽象类必须得实现里面的抽象方法

  • 4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。

  • 5、抽象类不能被实例化,只有继承它的子类可以

//定义抽象类,使用abstract修饰

abstract class Class09{
  void fun01();//这里是定义抽象方法
}
//继承抽象类
class Class10 extends Class09 {
  @override
  void fun01(){//这里是实现抽象方法
    print("定义自己的抽象方法");
  }
}

void main(){
  var class10=new Class10();
  class10.fun01();//打印:定义自己的抽象方法
}

案例:
定义一个Animal 类要求它的子类必须包含eat方法

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('小猫在跑');
  }

}

main(){

  Dog d=new Dog();
  d.eat();//小狗在吃骨头
  d.printInfo();//我是一个抽象类里面的普通方法

   Cat c=new Cat();
  c.eat();//小猫在吃老鼠
  c.printInfo();//我是一个抽象类里面的普通方法


  // Animal a=new Animal();   //报错,抽象类没法直接被实例化

}

接口

特点:使用implements关键字

/*
定义一个DB库 支持 mysql  mssql  

mysql  mssql  两个类里面都有同样的方法

*/


abstract class Db{   //当做接口   接口:就是约定 、规范
    String uri;      //数据库的链接地址
    add(String data);
    save();
    delete();
}

class Mysql implements Db{
  
  @override
  String uri;

  Mysql(this.uri);

  @override
  add(data) {
    // TODO: implement add
    print('这是mysql的add方法'+data);
  }

  @override
  delete() {
    // TODO: implement delete
    return null;
  }

  @override
  save() {
    // TODO: implement save
    return null;
  }

  remove(){
      
  }

  
}

class MsSql implements Db{
  @override
  String uri;
  MsSql(this.uri);
  @override
  add(String data) {
    print('这是mssql的add方法'+data);
  }

  @override
  delete() {
    // TODO: implement delete
    return null;
  }

  @override
  save() {
    // TODO: implement save
    return null;
  }


}

main() {

  Mysql mysql=new Mysql('xxxxxx');

  mysql.add('1243214');//这是mysql的add方法1243214


  MsSql mssql=new MsSql('xxxxxx');

  mssql.add('1243214');//这是mssql的add方法1243214

  


  
}

extends抽象类 和 接口implements 的区别:

  • 1、如果要复用抽象类里面的方法,并且要用抽象方法约束子类的话我们就用extends继承抽象类

  • 2、如果只是把抽象类当做标准的话我们就用接口implements实现抽象类.

多态

特点:

  • 用abstract关键字
  • 子类的实例赋值给父类的引用。
  • 多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
abstract class Animal{
 eat();   //抽象方法 
}

class Dog extends Animal{
 @override
 eat() {
    print('小狗在吃骨头');
 }
 run(){
   print('小狗run');
 }
}
class Cat extends Animal{
 @override
 eat() {   
   print('小猫在吃老鼠');
 }
 run(){
   print('小猫run');
 }
}

main(){
 //普通实例化和调用 

 // Dog d=new Dog();
 // d.eat();//小狗在吃骨头
 // d.run();//小狗run


 // Cat c=new Cat();
 // c.eat();//小猫在吃老鼠
 // c.run();//小猫run


//多态的使用:子类的实例赋值给父类的引用;多态就是父类定义一个方法不去实现,让继承他的子类去实现

 Animal d=new Dog();
 d.eat();//小狗在吃骨头



 Animal c=new Cat();
 c.eat();//小猫在吃老鼠




}

静态变量和静态函数的使用

class Class11{
  static int a=3;//静态变量
  int b=4;//实例变量

  static void fun01(int c){//静态方法
    print(c);
  }
  void fun02(){//实例方法
    print(this.b);
  }
}

void main (){
  var class11=new Class11();
  print(class11.b);//4,实例变量
  print(Class11.a);//3,静态变量
  class11.fun02();//4 ,实例函数调用
  Class11.fun01(44);//44 静态函数调用
}

枚举类型
特点:使用enum修饰类,每个枚举值都有一个唯一值,不用实例化,直接枚举名点values获取所有枚举值.

//定义枚举
enum Week { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
void main() {
  List<Week> list = Week.values; //values属性获取所有枚举值
  print(
      list); //[Week.Monday, Week.Tuesday, Week.Wednesday, Week.Thursday, Week.Friday, Week.Saturday, Week.Sunday]

  list.forEach((e) {
    print(e); //依次如下打印
    //     Week.Monday
    //     Week.Tuesday
    //     Week.Wednesday
    //     Week.Thursday
    //     Week.Friday
    //     Week.Saturday
    //     Week.Sunday
    print(e.index);//依次如下打印
    //     0
    //     1
    //     2
    //     3
    //     4
    //     5
    //     6
  });

}

类实例化对象的操作符

?     条件运算符 (了解)
as    类型转换
is    类型判断
..    级联操作 (连缀)  (很常见)
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
 print("${this.name}---${this.age}");
}
}

void main() {
// ?运算符
Person p;
print(p); //null
p?.printInfo(); //没执行后面方法.这是条件运算符判断,如果?前面是空,则不会执行后面操作

Person p = new Person("张三", 18);
p?.printInfo(); //张三---18

// is运算符
Person p = new Person("张三", 18);
if (p is Person) {
 //is判断是否是后面的类型
 p.name = "李四";
}
p.printInfo(); //李四---18

Person p = new Person("张三", 18);
print(p is Object); //true

// ..运算符
Person p = new Person("张三", 18);

// 等同于
p
 ..name = "李四"
 ..age = 30
 ..printInfo(); //李四---30
}

继承

简单继承

class Person {
  String name='张三';
  num age=20; 
  void printInfo() {
    print("${this.name},${this.age}");  
  } 
}
class Web extends Person{

}

main(){   

  Web w=new Web();
  print(w.name);//张三
  w.printInfo();//张三,20
 
}

super关键字的使用

子类给父类传参

class Person {
  String name;
  num age; 
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}


class Web extends Person{
  // Web(String name, num age) : super(name, age){//这里是子类给父类传参

  // }
  // 可以简写
   Web(String name, num age) : super(name, age);
  
}

main(){ 
  Web w=new Web('张三', 12);

  w.printInfo();//张三---12


}

给子类添加自己的属性

class Person {
  String name;
  num age; 
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}


class Web extends Person{
  String sex;
  Web(String name, num age,String sex) : super(name, age){
    this.sex=sex;
  }
  run(){
   print("${this.name}---${this.age}--${this.sex}");  
  }
  
}

main(){ 

  Web w=new Web('张三', 12,"男");

  w.printInfo();//张三---12

  w.run();//张三---12--男

}

子类给父类命名构造函数传参

class Person {
  String name;
  num age; 
  Person(this.name,this.age);
  Person.xxx(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}


class Web extends Person{
  String sex;
  Web(String name, num age,String sex) : super.xxx(name, age){
    this.sex=sex;
  }
  run(){
   print("${this.name}---${this.age}--${this.sex}");  
  }
  
}

main(){ 

  Web w=new Web('张三', 12,"男");

  w.printInfo();//张三---12

  w.run();//张三---12--男

}

子类覆写父类的方法

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');
  }
  //覆写父类的方法
  @override       //可以写也可以不写  建议在覆写父类方法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
  @override
  work(){
    print("${this.name}的工作是写代码");
  }

}





main(){ 

  Web w=new Web('李四',20);

  w.printInfo();//姓名:李四---年龄:20

  w.work();//李四的工作是写代码
 
}

子类里面调用父类的方法

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       //可以写也可以不写  建议在覆写父类方法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
  

}


main(){ 

  Web w=new Web('李四',20);

  w.printInfo();//姓名:李四---年龄:20

  w.run();//run 李四在工作...
 
}

mixins多类继承

class With1 {
  String getName() => 'With1';//三个类都有该方法
  String getAge()=> "With1   10" ;//该类独有
}

class With2 {
  String getName() => 'With2';//三个类都有该方法
  String getColor() => "With2   red";//该类独有
  int getNum()=> 6;//该类和OtherClass都有
  String getFruit()=>"With2   banana";
}

class OtherClass {
  String getName() => 'OtherClass';//三个类都有该方法
  int getNum() => 3; //该类和With2都有
  int getDesk() => 333;//该类独有

  String getPhone()=>"OtherClass   huawei";//该类和子类
  String getFruit()=>"OtherClass   apple";

}

class Child1 extends OtherClass with With1 ,With2 {
  //重写父类
  @override
  String getPhone() {
    return "Child1   iphone";
  }
  @override
  String getFruit() {
    return "Child1  oriange";
  }
}
class Child2 extends OtherClass with With2, With1 {}
void main(){
    print("class Child1 extends OtherClass with With1 ,With2 {}");
    Child1 c1 = Child1();
    print(c1.getPhone());//Child1   iphone     重写了函数,调用时用的是自身的函数
    print(c1.getFruit());//Child1  oriange     重写了函数,调用时用的是自身的函数
    print(c1.getDesk());//333      调用的是OtherClass的函数  With1 With2中没有同名函数
    print(c1.getNum());//6       调用的是With2中的函数
    print(c1.getAge());//With1   10        调用的是With1中的函数
    print(c1.getColor());//With2   red       调用的是With2中的函数
    print(c1.getName());//With2          调用的是With2中的函数    With2在声明顺序中更靠后

    print("-----------------------");
    print("class Child2 extends OtherClass with With2, With1 {}");
    Child2 c2 = Child2();
    print(c2.getPhone());//OtherClass   huawei     没有重写函数,调用时用的是OtherClass的函数
    print(c2.getFruit());//With2   banana    没有重写函数,调用时用的是With2的函数,虽然OtherClass也有,但With2在声明顺序中更靠后
    print(c2.getDesk());//333     调用的是OtherClass的函数  With1 With2中没有同名函数
    print(c2.getNum());//6     调用的是With2中的函数
    print(c2.getAge());//With1   10       调用的是With1中的函数
    print(c2.getColor());//With2   red      调用的是With2中的函数
    print(c2.getName());//With1      调用的是With1中的函数    With1在声明顺序中更靠后
}

解释说明:

  • A extends B with C,D{}。

  • A 继承了B 并拥有了C和D所有的属性和函数,可以用A的实例直接调用CD的属性方法。

  • 如果B有函数fun1,A重写了这个函数 那么以后A的实例调用的fun1,都是A重写后的方法。

  • 如果B有函数fun1,CD中也有函数fun1,A重写了这个函数 那么以后A的实例调用的fun1,都是A重写后的方法。

  • 如果B有函数fun1,CD中也有函数fun1,A没有重写这个函数 那么以后A的实例调用的fun1,是声明方法时最后的那个类的函数,比如“A extends B with C,D”,那么就是D中的fun1,如果是“A extends B with D,C”,那么就是C中的fun1。也就是说优先级是从后向前的(前提是子类没有重写函数)。

隐式接口

特点:

  • 一个类可以实现一个或多个接口,也就是可以实现多个类,用implements关键字。
  • Impostor 实现了类Person ,那么Impostor 中必须重写Person 中所有的属性和函数。
// person 类。 隐式接口里面包含了 greet() 方法声明。
class Person {
  // 包含在接口里,但只在当前库中可见。
  final _name;

  // 不包含在接口里,因为这是一个构造函数。
  Person(this._name);

  // 包含在接口里。
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// person 接口的实现。
class Impostor implements Person {
  @override
  get _name => '';
  
  @override
  String greet(String who) => 'Hi $who. Do you know who I am?';
}

//声明greetBob函数
String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy')));//Hello, Bob. I am Kathy.
  print(greetBob(Impostor()));//Hi Bob. Do you know who I am?
}

你可能感兴趣的:(十八.Flutter)