# 类与对象
面向对象编程(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
}
# 静态成员
- 使用
static关键字修饰 - 静态方法不能访问非静态成员,非静态方法可以访问静态成员。
 
//静态成员
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类型判断,如果对象具有指定类型则为trueis!类型判断,如果对象具有指定类型则为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中类的继承:
- 子类使用
extends关键字来继承父类 - 子类会继承父类里面可见的属性和方法,但是不会继承构造函数
 - 子类能覆写父类的方法 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中抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
- 抽象类通过
abstract关键字定义。 - Dart中抽象类方法不能用
abstract声明,Dart中没有方法体的方法称为抽象方法。 - 如果子类继承抽象类,就必须实现父类的抽象方法。
 - 如果把抽象类当接口使用,就必须实现抽象类中的所有属性和方法。
 - 抽象类不能被实例化,只有继承他的子类可以。
 
extends抽象类与implements的区别:
- 如果要复用抽象类里的方法,并且要用抽象方法约束子类的话,我们就是用
extends继承抽象类。 - 如果只是将抽象类当做标准就是用
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也有接口,区别在于:
- Dart的接口没有
interface关键字,普通类和抽象类都可以作为接口被实现,使用implements关键字实现。 - Dart中,如果接口的实现类是普通类,会将普通类和抽象类中属性和方法全部覆写一遍
 - 抽象类可以定义抽象方法,普通类不行,建议使用抽象类做接口。
 
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的使用条件:
- 作为Mixins的类智能继承自Object,不能继承自其他类
 - 作为Mixins的类不能有构造函数
 - 一个类可以Mixins多个Mixins类
 - 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
}
← 函数 泛型 泛型方法 泛型类 泛型接口 →