Dart 类和对象

131 阅读3分钟

Dart是一门使用类和单继承的面向对象语言,有三个基本特征:封装,继承,多态, 所有的类都继承自Ojbect。

类的初始化

  • 类的属性需要赋初始值 或 标记延迟初始化 或 作空处理。

  • 类的同名方法即默认的构造函数,也可命名构造函数

  • 使用final 声明的属性只有getter方法,只读

  • 子类重写父类方法,建议@override标记

Class Person extends Object {
   
   int age = 10;       //直接初始化
   String ? name ;     //空处理
   late String sex;    //延迟初始化
   
   //默认构造函数
   Person(this.age, this.name, this.sex);
   
   //命名构造函数
   Person.fromJson(Map json){
      this.name = json["mame"];
      this.age  = json["age"];
      this.sex  = json["sex"];
   }
   
   void sayHello() {
        print("my age is:" + this.age.toString());
    }
}

//调用
var person = Person(10, "zhangsan", "W");
person.sayHello();

获取对象的类型

void main() {
  Person p = Person("张三");
  print(p.runtimeType);//打印Person
}

属性访问器

每个字段都有一个隐匿的Setter/Getter 方法,可以通过关键字getset字段重写来扩展功能。(final 或 const 修饰的字段只能有getter 方法)

class Rectangle {

  num left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  num get right => left + width;
  set right(num value) => left = value - width;
  
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}

静态成员变量/方法

静态 static 成员对于面向对象而已也是一个非常重要的概念,它和普通成员有着非常大的区别。静态成员由  本身直接访问,不依附于 对象。 同样,static也可以修饰静态方法,只能类本身调用。

class Person { 
    String name; 
    
    //静态成员
    static String nation = "Chinese";
    
    Person(this.name,this.nation);
    
    //静态方法
    static void printNation(){ 
        print("现在朝代是: $nation"); 
    }
    
    void say(){ 
        print("我叫$name,我是$nation人");
     }
 }
 

子类继承需要首先实现构造函数

class Woker extends Person {

   int salary = 0;
   //继承的自定义类需要先实现构造方法
   Woker(super.age, super.name, super.sex, this.salary);
   
  @override //标记重写父类方法
  void sayHello() {
    print("my salary is:" + this.salary.toString());
  }
}

级连操作符

.. ?.. 在同一个对象上连续调用多个对象的变量或方法

var person = new Person();

person.name=’Tom’;

Person.age=20;


优化后:

void main() {

    var person = Person();
    person
        ..name = 'Tom'
        ..age = 20
        ..work();
}


class Person {

    String name = '';
    int age = 0;
    void work() {
        print('work...');
    }
}


再优化

void main() {

   Person()
    ?..name = 'Tom'
    ..age = 20
    ..work();
}


class Person {

    String name = '';
    int age = 0;
    void work() {
        print('work...');
    }
}

工厂构造函数

并不是任何时候都需要创建一个新的对象,可以返回一个已经缓存好的对象或该类的子类对象。

//待

将类对象作为函数调用

Dart 允许我们将一个类的对象作为函数来调用,只需要实现 call() 函数即可:

class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf =  WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out');
}

抽象类

抽象类只负责方法的声明,不负责实现,也不能初始化实例而由子类实现方法 抽象类可以被继承(extends)或 实现(implements).

abstract class Animal {

    void haveBaby(); //只有方法名称,没有方法实现
}

class Cat extends Animal {

    @override
    void haveBaby() {
      // TODO: implement haveBaby
    }
}
class Monkey extends Animal {

    @override
    void haveBaby() {
      // TODO: implement haveBaby
    }
}

类的混合 Mixin

虽然是单继承, 但Dart 可以用with 混合其它多个类的方法

class Eat {
    void eat() {
        print("eat...");
    }
    void sayHello() { 
      print("eat hello");
    }
}
class Sleep {
    void sleep() {
        print("sleep...");
    }
    void sayHello() { 
      print("sleep hello");
    }
}

注意:

子类在混合其它类的方法时,优先调用自身的方法,其次是混合中的最后一个类,其次是父类

class Woker extends Person with Eat, Sleep {

    int salary = 0;
   //继承的自定义类需要先实现构造方法
   Woker(super.age, super.name, super.sex, this.salary);
    
    void sayHello() {
       print("my age is:" + this.age.toString());
    }
}

//调用方法
var woker = Woker();
woker.sayHello();

泛型

  • 泛型方法
//传入的实参是什么类型,则“T”就代表该类型
T getData<T>(T value) {   
  return value;
}
 
//<String>中的String为检验传的参数是否是String类型
print(getData<String>("深圳"));                           
  • 泛型类
//定义泛型类
class ListClass<T> {                                              
  List list = new List<T>();
 
  void printInfo() {
    for (var i = 0; i < this.list.length; i++) {
      print(this.list[i]);
    }
  }
  void add(T value) {
    this.list.add(value);
  }
}
 

没有指定类型T的实际类型,因此没有类型校验,传各种类型

main() {

  //实例化一个泛型类
  ListClass list =  ListClass(); 
  list.add(1);                                        
  list.add(2);
  list.add(3);            //添加int类型数据
  list.add("深圳");        //添加String类型数据,不会报错
  list.printInfo();                   

指定的类型,在调用其中该泛型类中的方法时会进行类型校验

main() {

  //指定了实例化ListClass 类时传入的类型为int类型
  ListClass list = new ListClass<int>();                     
  list.add(1);
  list.add(2);
  list.add(3);
  list.add("深圳");    //报错
  list.printInfo();
}
  • 泛型接口 在具体的类实现了泛型接口后,实例化该类需指定传入的类型:
//抽象类Cache,此处做接口使用
abstract class Cache<T> {                                     
  getByKey(String key);
 
  setByKey(String key, T value);
}
 
//Cache类的实现类
class FileCache<T> implements Cache<T> {                       
  @override
  getByKey(String key) {
  }
 
  @override
  setByKey(String key, T value) {}
}
 
main() {

  //实例化FileCache对象的时候,指定"T"的类型
  FileCache fileCache = new FileCache<String>();               
  fileCache.setByKey("name", "深圳");
  
  //报错,指定setByKey()的第二个参数为String类型,但是这里传入了int类型
  fileCache.setByKey("name", 123);                             
}