Dart13类

1.声明一个类

class class_name {  
   <fields> 
   <getters/setters> 
   <constructors> 
   <functions> 
}

示例:

class Car {  
   // field 
   String engine = "EA888";  

   // function 
   void disp() { 
      print(engine); 
   } 
}

2.构造函数

2.1.默认构造函数

与类同名的函数,在实例化时,自动被调用

class Point {
  num x, y;
  // 默认构造函数
  Point() {
    print('这是默认的构造函数,实例化时,会第一个被调用。');
  }
}

void main() {
  Point p = new Point();
  print(p.x);
  // 这是默认的构造函数,实例化时,会第一个被调用。
  // null
}

构造函数是类的特殊函数,负责初始化类的变量。

class Car { 
   String engine; 
   Car(String engine) { 
      this.engine = engine; 
      print("The engine is : ${engine}"); 
   } 
}

void main() { 
   Car c1 = new Car('EA888'); 
}

2.2.命名构造函数

在类中使用命名构造函数(类名.函数名)实现多个构造器,可以提供额外的清晰度

语法:

class_name.constructor_name(param_list)

以下示例显示如何在Dart中使用命名构造函数:

void main() {           
   Car c1 = new Car.namedConst('EA888');                                       
   Car c2 = new Car(); 
}   

class Car {                   
   Car() {                           
      print("Non-parameterized constructor invoked");
   }                                   
   Car.namedConst(String engine) { 
      print("The engine is : ${engine}");    
   }                               
}

执行上面示例代码,得到以下结果:

The engine is : EA888 
Non-parameterized constructor invoked

2.3.常量构造函数

如果类生成的对象不会改变,可以通过常量构造函数使这些对象成为编译时常量

class Book {
  // 属性必须通过 final 声明
  final String name;
  // const String author; // Only static fields can be declared as const
  final String author;

  // 常量构造函数,必须通过 const 声明
  const Book(this.name, this.author);
}

void main() {
  // 声明不可变对象,必须通过 const 关键字
  var c1 = const Book('西游记', '吴承恩');
  var c2 = const Book('西游记', '吴承恩');
  print(c1 == c2); // true

  // 常量构造函数,可以当作普通构造函数使用
  var c3 = new Book('西游记', '吴承恩');
  var c4 = new Book('西游记', '吴承恩');
  print(c3 == c4); // false

  // 实例化时,new关键字可以省略
  var c5 = new Book('西游记', '吴承恩');
  var c6 = new Book('西游记', '吴承恩');
  print(c5 == c6); // false
}

2.4.identical

检查两个引用是否指向同一个对象。

class Book {
  // 属性必须通过 final 声明
  final String name;
  final String author;

  // 常量构造函数,必须通过 const 声明
  const Book(this.name, this.author);
}

void main() {
  // 声明不可变对象,必须通过 const 关键字
  var c1 = const Book('西游记', '吴承恩');
  var c2 = const Book('西游记', '吴承恩');
  print(c1 == c2); // true
  print(identical(c1, c2)); // true

  // 常量构造函数,可以当作普通构造函数使用
  var c3 = new Book('西游记', '吴承恩');
  var c4 = new Book('西游记', '吴承恩');
  print(c3 == c4); // false
  print(identical(c3, c4)); // false
}

2.5.工厂构造函数

通过 factory 声明,工厂函数不会自动生成实例,而是通过代码来决定返回的实例

class Car {
  int wheels;

  static Car instance;

  // 命名构造函数
  Car.newCar(this.wheels);

  // 工厂构造函数 -- 接受一个可选参数并赋默认值4
  factory Car([int wheels = 4]) {
    // 工厂构造函数中,不能使用 this 关键字
    // print(this.wheels); // Invalid reference to 'this' expression

    // 第一次实例化
    if (Car.instance == null) {
      Car.instance = new Car.newCar(wheels);
    }
    // 非第一次实例化
    return Car.instance;
  }
}

void main() {
  // Car c1 = new Car();
  // Car c2 = new Car(6);
  // print(c1.wheels); // 4
  // print(c2.wheels); // 4

  Car c1 = new Car(6);
  Car c2 = new Car();
  print(c1.wheels); // 6
  print(c2.wheels); // 6
  print(c1 == c2); // true
}

3.Getter、Setter

默认的 getter/setter 与每个类相关联。但是,可以通过显式定义 setter/getter 来覆盖默认值。getter 没有参数并返回一个值,setter 只有一个参数但不返回值。

示例:

class Student { 
   String name; 
   int age; 

   String get stud_name { 
      return name; 
   } 

   void set stud_name(String name) { 
      this.name = name; 
   } 

   void set stud_age(int age) { 
      if(age<= 15) { 
        print("Age should be greater than 15"); 
      }  else { 
         this.age = age; 
      } 
   } 

   int get stud_age { 
      return age;     
   } 
}  

void main() { 
   Student s1 = new Student(); 
   s1.stud_name = 'Maxsu'; 
   s1.stud_age = 0; 
   print(s1.stud_name); 
   print(s1.stud_age); 
}

4.访问修饰

Dart 没有访问修饰符(public, protected, private),在 Dart 类中,默认的访问修饰符是公开的(即 public)

如果要使用私有属性(private),需要同时满足以下两个条件:

  • 属性或方法以_(下划线)开头
  • 只有把类单独抽离出去,私有属性和方法才起作用
class Person {
  String name;

  // 声明私有属性
  num _age = 8;

  Person(this.name);

  num getAge() {
    return this._age;
  }
}
import 'lib/Person.dart';

void main() {
  Person p = new Person('Rogers');
  print(p.name); // Rogers

  // 访问私有属性
  // print(p._age); // The getter '_age' isn't defined for the type 'Person'.

  print(p.getAge()); // 8
}

5.继承

一个类使用extends关键字从另一个类继承,子类继承除父类的构造函数之外的所有属性和方法。

示例

class Shape { 
   void cal_area() { 
      print("calling calc area defined in the Shape class"); 
   } 
}  
class Circle extends Shape {}

void main() { 
   var obj = new Circle(); 
   obj.cal_area(); 
}

6.方法重写

方法重写是子类在其父类中重新定义方法的机制。以下示例说明了相同的情况:

class Parent { 
   void m1(int a){ print("value of a ${a}");} 
}  
class Child extends Parent { 
   @override 
   void m1(int b) { 
      print("value of b ${b}"); 
   } 
}

void main() { 
   Child c = new Child(); 
   c.m1(12); 
} 

重写方法时,函数参数的数量和类型必须匹配。如果参数数量或其数据类型不匹配,Dart编译器将抛出错误。

7.static

static关键字可以应用于类的数据成员,即字段和方法。静态变量保留其值,直到程序完成执行。静态成员由类名引用。

示例

class StaticMem { 
   static int num;  
   static disp() { 
      print("The value of num is ${StaticMem.num}")  ; 
   } 
}  

void main() { 
   StaticMem.num = 12;  
   // initialize the static variable } 
   StaticMem.disp();   
   // invoke the static method 
}

执行上面示例代码,得到以下结果 -

执行上面示例代码,得到以下结果 - 

8.super

supper关键字可用于引用超类的变量,属性或方法等等。

class Parent { 
   String msg = "message variable from the parent class"; 
   void m1(int a){ print("value of a ${a}");} 
} 
class Child extends Parent { 
   @override 
   void m1(int b) { 
      print("value of b ${b}"); 
      super.m1(13); 
      print("${super.msg}")   ; 
   } 
}

void main() { 
   Child c = new Child(); 
   c.m1(12); 
} 

9.抽象类

使用 abstract 修饰符来定义抽象类

abstract class Doer {
  // 定义实例变量和方法 ...

  void doSomething(); // 定义一个抽象方法。
}

class EffectiveDoer extends Doer {
  void doSomething() {
    // 提供方法实现,所以这里的方法就不是抽象方法了...
  }
}

10.接口

通过 implements 实现多个接口

abstract class A {
  late String name;
  printA();
}

abstract class B {
  printB();
}

class C implements A, B {
  @override
  late String name;
  @override
  printA() {
    print('printA');
  }

  @override
  printB() {
    print('printB');
  }
}

void main() {
  C c = new C();
  c.printA(); // printA
  c.printB(); // printB
}

11.mixins

在 Dart 中本不可以实现多继承,利用 mixins 可实现类似多继承的功能。

  • 作为 mixins 的类只能继承自 Object,不能继承其他类。
  • 作为 mixins 的类不能有构造函数。
  • 一个类可以 mixins 多个 mixins 类。
  • mixins 绝不是继承,也不是接口,而是一种全新的特性。
class A {
  String info="this is A";
  void printA(){
    print("A");
  }
}

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

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

  void run() {
    print("Person Run");
  }
}

// 使用 with 关键字实现 mixins
class C with A,B{}

// 既继承自 Person 又 mixins A 和 B,with 后跟的类有顺序之分,后类的方法会覆盖前类的方法
class D extends Person with A, B {
  C(String name, num age) : super(name, age);
}

void main(){
  var c=new C();  
  c.printA(); // A
  c.printB(); // B
  print(c.info); // this is A

  var D = new C('张三', 20);
  D.printInfo(); // 张三----20
  D.run(); // B Run
}

mixins 的类型

mixins的类型就是其超类的子类型。

class A {
  String info="this is A";
  void printA(){
    print("A");
  }
}

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

class C with A,B{}

void main(){  
   var c=new C();  
   
  print(c is C);    //true
  print(c is A);    //true
  print(c is B);    //true

  var a=new A();
  print(a is Object); //true
}