# 类与对象

面向对象编程(OOP)d的三个基本特征:封装、继承、多态

Dart所有的东西皆为对象,所有对象继承自Object类。

Dart是一门使用类和单继承的面向对象语言,所有对象都是类的示例,并且所有类都是Object的子类。

一个类通常有属性及方法组成。

class Person {
  String name;
  int age;

  void setName(String name) {
    this.name = name;
  }

  String getName() {
    return this.name;
  }

  void setAge(int age) {
    this.age = age;
  }

  int getAge() {
    return this.age;
  }
}

main() {
  var p = new Person();
  p.setName('Sogrey');
  print(p.getName());//Sogrey
  p.age = 30;
  print(p.getAge());//30
}

# 构造函数

像Java一样,类的构造函数:

  Person([String name,int age]){//[]内为可选参数
    print('构造方法,实例化时自动触发');
    this.name = name;
    this.age = age;
  }

更简洁,与上同效:

  Person([this.name,this.age]);

# 命名构造函数

  Person.work(){
    print('命名构造函数');
  }

  var work = new Person.work();

# 引入外部类

import关键字

import 'lib/Person.dart';

main() {
  var p = new Person();
  p.setName('Sogrey');
  print(p.getName());
  p.age = 30;
  print(p.getAge());
}

Person.dart:

class Person {
  String name;
  int age;

  // Person([String name,int age]){
  //   print('构造方法,实例化时自动触发');
  //   this.name = name;
  //   this.age = age;
  // }

  Person([this.name,this.age]);

  Person.work(){
    print('命名构造函数');
  }

  void setName(String name) {
    this.name = name;
  }

  String getName() {
    return this.name;
  }

  void setAge(int age) {
    this.age = age;
  }

  int getAge() {
    return this.age;
  }
}

# 私有变量、属性

变量前加下划线_.

私有属性外部不能访问,只能在当前类内访问。

如何访问私有属性,定义一个共有的方法,返回该私有属性。私有方法一样。

# getter/setter 方法

class Rect {
  num height;
  num width;
  Rect(this.width, this.height);
  // num area(){
  //   return this.width*this.height;
  // }
  //简写
  get area {
    return this.width * this.height;
  }

  //Setters should declare exactly one required parameter.
  //Setters应该只声明一个必需的参数。
  set areaWidth(num width) {
    this.width = width;
  }

  set areaHeight(num height) {
    this.height = height;
  }
}

main() {
  var r = new Rect(20, 2);
  // print(r.area());
  print(r.area);//40

  r.areaWidth = 20;
  r.areaHeight = 10;
  print(r.area);//200
}

# 实例化之前做些事

class Rect {
  num height;
  num width;

  // 实例化之前做些事( 给属性赋默认值 )
  Rect():width=2, height=20{

  }

  // num area(){
  //   return this.width*this.height;
  // }
  //简写
  get area {
    return this.width * this.height;
  }

  //Setters should declare exactly one required parameter.
  //Setters应该只声明一个必需的参数。
  set areaWidth(num width) {
    this.width = width;
  }

  set areaHeight(num height) {
    this.height = height;
  }
}

main() {
  var r0 = new Rect();
  print(r0.area);//40
}

# 静态成员

  1. 使用static关键字修饰
  2. 静态方法不能访问非静态成员,非静态方法可以访问静态成员。
//静态成员

class Animal {
  static String type = 'Animal';
  static String name = 'Dog';
  static String getName() {
    return name;
  }

  void setName(n) {
    name = n;
  }
}
main() {
  var a = new Animal();
  a.setName('Cat');
  print(Animal.getName());//Cat
}

# 操作符

  • ?条件运算符
  • as类型转换
  • is类型判断,如果对象具有指定类型则为true
  • is!类型判断,如果对象具有指定类型则为false
  • ..级联操作(链式调用)
  String aa=null;

  // print(aa.indexOf('a'));
  // Unhandled exception:
  // NoSuchMethodError: The method 'indexOf' was called on null.
  // Receiver: null
  // Tried calling: indexOf("a")

  print(aa?.indexOf('a'));//null

  var a = new Animal();
  if(a is Animal){
    print('a is Animal');
  }

  (a as Animal).setName('Fish');


  class Person {
    String name;
    int age;
    String sex;

    String getInfo() {
      return 'My name is ${this.name},${this.sex},${this.age},${this.age}';
    }
  }
  Person pp = new Person();
  pp
    ..name = 'Sogrey'
    ..age = 31
    ..sex = '男';

  print(pp.getInfo());

  //My name is Sogrey,男,31 years old.

# 类的继承

Dart中类的继承:

  1. 子类使用extends关键字来继承父类
  2. 子类会继承父类里面可见的属性和方法,但是不会继承构造函数
  3. 子类能覆写父类的方法 getter和setter
class Person {
  String name;
  int age;
  String sex;

  Person([this.name, this.age]);
  void setName(String name) {
    this.name = name;
  }
}
class Child extends Person{

  Child(String name,int age,String sex):super(name,age){
    this.sex = sex;
  }
  //覆写父类方法
  void setName(String name) {
    this.name ='Child\'s ${name}';
  }
}

Child c = new Child('张三', 12,'男');
print(c.getInfo());
//My name is 张三,男,12 years old.
c.setName('李四');
print(c.getInfo());
//My name is Child's 李四,男,12 years old.

# 抽象类

Dart中抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。

  1. 抽象类通过abstract关键字定义。
  2. Dart中抽象类方法不能用abstract声明,Dart中没有方法体的方法称为抽象方法。
  3. 如果子类继承抽象类,就必须实现父类的抽象方法。
  4. 如果把抽象类当接口使用,就必须实现抽象类中的所有属性和方法。
  5. 抽象类不能被实例化,只有继承他的子类可以。

extends抽象类与implements的区别:

  1. 如果要复用抽象类里的方法,并且要用抽象方法约束子类的话,我们就是用extends继承抽象类。
  2. 如果只是将抽象类当做标准就是用implements实现继承。

案例:定义抽象Person类,要求子类必须实现getSex方法:

abstract class Person {
  //抽象类通过`abstract`关键字定义
  getSex(); //没有方法体的方法称为抽象方
  String getMsg(){
    return '抽象类中的普通方法';
  }
}

class Man extends Person {
  //子类必须实现父类里的抽象方法
  
  getSex() {
    return 'Man';
  }
}

class Woman extends Person {
  //子类必须实现父类里的抽象方法
  
  getSex() {
    return 'Woman';
  }
}

main() {
  var man = new Man();
  print(man.getSex()); //Man
  print(man.getMsg()); //抽象类中的普通方法
  var woman = new Woman();
  print(woman.getSex()); //Woman
  print(woman.getMsg()); //抽象类中的普通方法
}

# 多态

允许将子类类型的指针赋值给父类类型的指针,统一个函数调用会有不同的执行结果。

子类的实例赋值给父类的引用。

多态就是父类定义一个方法不去实现,由子类实现,不同子类又不用的实现方法,得到的执行结果也不同。

abstract class Person {
  //抽象类通过`abstract`关键字定义
  getSex(); //没有方法体的方法称为抽象方
}

class Man extends Person {
  //子类必须实现父类里的抽象方法
  
  getSex() {
    return 'Man';
  }

  String getMsg() {
    return '抽象类Man中的普通方法';
  }
}

class Woman extends Person {
  //子类必须实现父类里的抽象方法
  
  getSex() {
    return 'Woman';
  }

  String getMsg() {
    return '抽象类Woman中的普通方法';
  }
}

main() {
  var man = new Man();
  print(man.getSex()); //Man
  print(man.getMsg()); //抽象类中的普通方法
  var woman = new Woman();
  print(woman.getSex()); //Woman
  print(woman.getMsg()); //抽象类中的普通方法

  Person man1 = new Man();
  print(man1.getSex()); //Man
  // print(man1.getMsg()); //子类的实例赋值给父类的引用,父类引用不能调用子类中的方法
}

# 接口

和Java一样,Dart也有接口,区别在于:

  1. Dart的接口没有interface关键字,普通类和抽象类都可以作为接口被实现,使用implements关键字实现。
  2. Dart中,如果接口的实现类是普通类,会将普通类和抽象类中属性和方法全部覆写一遍
  3. 抽象类可以定义抽象方法,普通类不行,建议使用抽象类做接口。
abstract class DB {
  add(String data);
  delete(int id);
  update(int id,String data);
  query(int id);
}

class MySql implements DB{
  
  add(String data) {
    // TODO: implement add
    return null;
  }

  
  delete(int id) {
    // TODO: implement delete
    return null;
  }

  
  query(int id) {
    // TODO: implement query
    return null;
  }

  
  update(int id, String data) {
    // TODO: implement update
    return null;
  }
}

class msSql implements DB{
  
  add(String data) {
    // TODO: implement add
    return null;
  }

  
  delete(int id) {
    // TODO: implement delete
    return null;
  }

  
  query(int id) {
    // TODO: implement query
    return null;
  }

  
  update(int id, String data) {
    // TODO: implement update
    return null;
  }
}

main(){
  MySql mySql = new MySql();
  mySql.add('data...');
  mySql.delete(1);
  //...


}

# 一个类实现多个接口

abstract class A {
  String name;
  printA();
}
abstract class B {
  printB();
}

class C implements A,B{

 //C继承自接口A和B,就要实现A和B中所有方法

  
  String name;
  
  printA(){
    //实现
  }
  
  printB(){
    //实现
  }
}

# Dart中的Mixins

Dart2中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} is ${this.age} years old.');
  }

  void run() {
    print('This is Person.');
  }
}

// 继承父类
class A {
  void printA() {
    print('A');
  }

  void run() {
    print('This is A.');
  }
}

class B {
  void printB() {
    print('B');
  }

  void run() {
    print('This is B.');
  }
}
//Mixins 类
class C extends Person with A, B {
  C(String name, num age) : super(name, age);
}

main() {
  var c = new C('Sogrey', 31);

  c.printInfo(); //Sogrey is 31 years old.

  // 继承自不同类,调用他们各自的方法
  c.printA(); //A
  c.printB(); //B

  // 继承多个类以及其他接口类中有相同方法,后面的会覆盖前面的
  c.run(); //This is B.

  // Mixins类的类型判断
  print(c is A); //true
  print(c is B); //true
  print(c is C); //true
  print(c is Person); //true
  print(c is Object); //true
}