美文网首页
Dart学习笔记06-类和对象

Dart学习笔记06-类和对象

作者: zombie | 来源:发表于2020-08-17 13:56 被阅读0次

1.类的定义

  • Dart中定义类用class关键字 类通常有两部分组成:成员(member)方法(method)
    代码示例:
class 类名 {
  类型 成员名;
  返回值类型 方法名(参数列表) {
    方法体
  }
}

// 在方法中使用属性(成员/实例变量)时,并没有加this 
// Dart在方法中通常使用属性时,会省略this,但是有命名冲突时,this不能省略
class Person {
  String name;
  eat() {
    print('$name在吃晚饭');
  }
}

main(List<String> args) {
  // 创建类的对象 从Dart2开始,new关键字可以省略
  var p1 = new Person();
  // 给对象的属性赋值
  p1.name = 'wang';
  // 使用 ?. 来代替 . , 可以避免因为左边对象可能为 null,导致的异常
  p1?.name = 'wang';
  // 调用对象的方法
  p1.eat(); // wang在吃晚饭
}

2.类的构造方法

2.1 普通构造方法

  • 当通过类创建一个对象时,会调用这个类的构造方法, 当类中没有明确指定构造方法时,将默认拥有一个无参的构造方法,默认构造方法没有参数并会调用父类的无参构造方法。我们也可以根据自己的需求,定义自己的构造方法 当有了自己的构造方法时,默认的构造方法将会失效,不能使用
    代码示例:
class Person1 {
  String name;
  int age;

  // Person1(String name, int age) {
  //   this.name = name;
  //   this.age = age;
  // }

  // 在实现构造方法时,通常做的事情就是通过参数给属性赋值 
  // 为了简化这一过程, Dart提供了一种更加简洁的语法糖形式.
  // 上面的构造方法等同于
  Person1(this.name, this.age);

  @override
  String toString() {
    return 'name = $name age = $age';
  }
}

var p2 = Person1('wang', 18);
print(p2); // name = wang age = 18

2.2. 命名构造方法

  • Dart不支持方法(函数)的重载,所以我们没办法创建相同名称的构造方法。我们需要使用命名构造方法
    ps:子类不会继承父类的构造方法。 子类不声明构造方法,那么它就只有默认构造方法
    代码示例:
class Person2 {
  String name;
  int age;

  Person2() {
    name = '';
    age = 0;
  }

  // 命名构造方法
  Person2.withArgements(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @override
  String toString() {
    return 'name = $name age = $age';
  }
}

var p3 = Person2();
print(p3); // name =  age = 0
var p4 = Person2.withArgements('wang', 18);
print(p4); // name = wang age = 18 

2.3. 初始化列表

代码示例:

class Point {
  final num x;
  final num y;
  final num distance;

  // 错误写法
  //   distance = sqrt(x * x + y * y);
  // }

  // 正确的写法 
  Point(this.x, this.y) : distance = sqrt(x * x + y * y);

  @override
  String toString() {
    return 'x = $x y = $y distance = $distance';
  }
}

var point = Point(10, 20);
print(point); // x = 10 y = 20 distance = 22.360679774997898
  • 上面这种初始化变量的方法, 我们称之为初始化列表(Initializer list)

2.4. 重定向构造方法

  • 在某些情况下, 我们希望在一个构造方法中去调用另外一个构造方法, 这个时候可以使用重定向构造方法
    代码示例:
class Person3 {
  String name;
  int age;

  Person3(this.name, this.age);
  // 在一个构造函数中,去调用另外一个构造函数注意:是在冒号后面使用this调用
  Person3.fromName(String name) : this(name, 0);
}

2.5. 常量构造方法

  • 在某些情况下,传入相同值时,我们希望返回同一个对象,这个时候,可以使用常量构造方法
    默认情况下,创建对象时,即使传入相同的参数,创建出来的也不是同一个对象
    代码示例:
class Person4 {
  String name;
  Person4(this.name);
}

var p5 = Person4('wang');
var p6 = Person4('wang');
print(identical(p5, p6)); // 使用identical(对象1, 对象2)函数来判断两个对象是否是同一个对象 false
  • 如果将构造方法前加const进行修饰,那么可以保证同一个参数,创建出来的对象是相同的 这样的构造方法就称之为常量构造方法
    拥有常量构造方法的类中,所有的成员变量必须是final修饰的
    为了可以通过常量构造方法,创建出相同的对象,使用const关键字
    如果是将结果赋值给const修饰的标识符时,const可以省略
    代码示例:
class Person5 {
  final String name;
  const Person5(this.name);
}

var p7 = const Person5('wang');
var p8 = const Person5('wang');
print(identical(p7, p8)); // true

2.6.工厂构造方法

  • Dart提供了factory关键字, 用于通过工厂去获取对象
    代码示例:
class Person6 {
  String name;
  static final Map<String, Person6> _cache = <String, Person6>{};
  factory Person6(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final p = Person6._internal(name);
      _cache[name] = p;
      return p;
    }
  }
  Person6._internal(this.name);
}

var p9 = Person6('wang');
var p10 = Person6('wang');
print(identical(p9, p10)); // true

3.setter和getter

  • Dart中类定义的属性是可以直接被外界访问的 如果我们希望监控这个类的属性被访问的过程,这个时候就可以使用settergetter
    代码示例:
class Cat {
  String color;

  String get getColor {
    return color;
  }

  set setColor(String color) {
    this.color = color;
  }

  Cat(this.color);
}

final cat = Cat('yellow');
cat.setColor = 'black';
print(cat.getColor); // black

4.类的继承

  • 面向对象的其中一大特性就是继承继承不仅仅可以减少我们的代码量,也是多态的使用前提
    Dart中的继承使用extends关键字,子类中使用super来访问父类
    父类中的所有成员变量和方法都会被继承,但是构造方法除外
    子类可以拥有自己的成员变量, 并且可以对父类的方法进行重写
    子类的构造方法在执行前,将调用父类的无参默认构造方法(没有参数且与类同名的构造方法)
    如果父类没有无参默认构造方法,则子类的构造方法必须在初始化列表中通过super显式调用父类的某个构造方法
    代码示例:
class Animal {
  int age;

  Animal(this.age);
  run() => print('奔跑');
}

class Person extends Animal {
  String name;

  Person(String name, int age)
      : name = name,
        super(age);

  @override
  run() {
    print('$name在奔跑');
  }

  @override
  String toString() {
    return 'name = $name, age = $age';
  }
}

Person p = Person('wang', 28);
p.run(); // wang在奔跑
print(p); // name = wang, age = 28

5.抽象类

  • 继承是多态使用的前提 所以在定义很多通用的调用接口时, 通常会让调用者传入父类,通过多态来实现更加灵活的调用方式. 但是,父类本身可能并不需要对某些方法进行具体的实现,所以父类中定义的方法,我们可以定义为抽象方法
    抽象方法在Dart中没有具体实现的方法(没有方法体)
    抽象方法,必须存在于抽象类中 抽象类是使用abstract声明的类
    抽象类不能实例化 抽象类中的抽象方法必须被子类实现
    抽象类中的已经被实现方法, 可以不被子类重写
    代码示例:
abstract class Shape {
  getArea();
}

class Circle extends Shape {
  double r;
  Circle(this.r);
  @override
  getArea() {
    return r * r * pi;
  }
}

class Reactangle extends Shape {
  double w;
  double h;

  Reactangle(this.w, this.h);

  @override
  getArea() {
    return w * h;
  }
}

6.隐式接口

  • Dart中的接口比较特殊, 没有一个专门的关键字来声明接口。默认情况下,定义的每个类都相当于默认也声明了一个接口,可以由其他的类来实现(因为Dart不支持多继承)
    代码示例:
abstract class Runner {
  run();
}

abstract class Flyer {
  fly();
}

// implements的方式要求必须对其中的方法进行重新实现
class SuperMan implements Runner, Flyer {
  @override
  run() {
    print('超人在奔跑');
  }

  @override
  fly() {
    print('超人在飞');
  }
}

var superMan = SuperMan();
superMan.run(); // 超人在奔跑
superMan.fly(); // 超人在飞

7.Mixin混入

  • 在通过implements实现某个类时,类中所有的方法都必须被重新实现(无论这个类原来是否已经实现过该方法)。但是某些情况下,一个类可能希望直接复用之前类的原有实现方案 但是Dart只支持单继承,那么意味着你只能复用一个类的实现
    Dart提供了另外一种方案: Mixin混入的方式,除了可以通过class定义类之外,也可以通过mixin关键字来定义一个类,只是通过mixin定义的类用于被其他类混入使用,通过with关键字来进行混入
    代码示例:
mixin Runner {
  run() {
    print('在奔跑');
  }
}

mixin Flyer {
  fly() {
    print('在飞翔');
  }
}

class SuperMan with Runner, Flyer {
  @override
  run() {
    print('superMan在奔跑');
  }
}

var superMan = SuperMan();
superMan.run(); // superMan在奔跑
superMan.fly(); // 在飞翔

8.类成员和方法

  • Dart中我们使用static关键字来定义类成员和方法
    代码示例:
class Student {
  String name;
  int grade;

  static String time;

  study() {
    print('$name在学习');
  }

  static gotoClass() {
    print('去上课');
  }
}

var student = Student();
student.name = 'wang';
student.grade = 4;
student.study(); // wang在学习

Student.time = '10点';
Student.gotoClass(); // 去上课

9.枚举类型

  • 枚举也是一种特殊的类, 通常用于表示固定数量的常量值
    枚举使用enum关键字来进行定义
    枚举的属性:
    index: 用于表示每个枚举常量的索引, 从0开始
    values: 包含每个枚举值的List
    代码示例:
enum Colors {red, green, blue}

print(Colors.red); // Colors.red
print(Colors.red.index);  // 0
print(Colors.green.index); // 1
print(Colors.blue.index); // 2
print(Colors.values); // [Colors.red, Colors.green, Colors.blue]

相关文章

网友评论

      本文标题:Dart学习笔记06-类和对象

      本文链接:https://www.haomeiwen.com/subject/qnpcohtx.html