美文网首页
Flutter学习(四)Dart语法类和对象

Flutter学习(四)Dart语法类和对象

作者: yanhooIT | 来源:发表于2020-03-31 22:33 被阅读0次

内部团队学习,以简单直接为主

概述

  • Dart是一个面向对象的语言,面向对象中非常重要的概念就是,类的实例就是对象

构造函数、类成员、方法以及枚举的定义

/** 代码输出结果如下
 * 普通构造函数:name=name1,age=18,sex=null
 * 命名构造函数:name=name2,age=28,sex=Gender.Girl
 * 命名构造函数:name=name3,age=30,sex=Gender.Boy
 * 初始化列表:name=name4,age=30,sex=null
 * 构造函数重定向:name=name5,age=0,sex=null
 * 常量构造函数:false
 * 工厂构造函数:true
 */
main(List<String> args) {
  // 普通构造函数
  var p1 = Person("name1", 18);
  print("普通构造函数:${p1.toString()}");

  // 命名构造函数
  var p2 = Person.withNameAgeSex("name2", 28, sex: Gender.Girl);
  print("命名构造函数:${p2.toString()}");

  // 命名构造函数
  var p3 =
      new Person.fromMap({'name': 'name3', 'age': 30, 'sex': Gender.Boy});
  print("命名构造函数:${p3.toString()}");

  // 初始化列表
  var p4 = new Person.withNameAge('name4', 30);
  print("初始化列表:${p4.toString()}");

  // 构造函数重定向
  var p5 = new Person.fromName('name5');
  print("构造函数重定向:${p5.toString()}");

  // 常量构造函数
  var p6 = Person2('name6');
  var p7 = Person2('name6');
  print("常量构造函数:${identical(p6, p7)}");

  // 工厂构造函数
  final p8 = Person3.withName("name7");
  final p9 = Person3.withName("name7");
  print("工厂构造函数:${identical(p8, p9)}");
}

/** 枚举(通常用于表示固定数量的常量值)
 * 枚举类型中有两个比较常见的属性:
 *    index: 用于表示每个枚举常量的索引, 从0开始.
 *    values: 包含每个枚举值的List.
 */
enum Gender { Boy, Girl }

// 类的定义
class Person {
  // 成员变量
  String name;
  int age;
  Gender sex;
  String desc;

  /** 构造函数
   * 1、当类中没有明确指定构造方法时,将默认拥有一个无参的构造方法
   * 2、当有了自己实现了构造函数时,默认的构造方法将会失效,不能再使用
   * 3、Dart本身不支持函数的重载
   * 4、构造函数的分类:
   *    (1)普通构造函数
   *    (2)命名构造函数
   *    (3)初始化列表
   *    (4)重定向构造函数
   *    (5)常量构造函数
   *    (6)工厂构造函数
   */

  /**
   * 普通构造函数
   */
  // Person(String name, int age) {
  //   this.name = name;
  //   this.age = age;
  // }
  // 简化语法糖,等同于上面的构造函数
  Person(this.name, this.age);

  /** 命名构造函数
   * 因为不支持方法(函数)的重载,所以我们没办法创建相同名称的构造方法
   * 我们需要使用命名构造方法来满足这一需求
   */
  // Person.withNameAgeSex(String name, int age, {Gender sex}) {
  //   this.name = name;
  //   this.age = age;
  //   this.sex = sex;
  // }
  // 简化语法糖,等同于上面的构造函数
  Person.withNameAgeSex(this.name, this.age, {this.sex});

  // 将一个Map转成对象,可以提供如下的构造方法
  Person.fromMap(Map<String, Object> map) {
    this.name = map['name'];
    this.age = map['age'];
    this.sex = map['sex'];
  }

  /** 初始化列表(类似C++语法)
   * 在初始化列表里可以写一些逻辑表达式,这个要比参数给默认值更加灵活,参数给默认值必须是给一个明确的值
   */
  Person.withNameAge(this.name, this.age, {String desc})
      : desc = desc ?? (age > 30 ? '中年人' : '年轻人');

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

  // 方法重写
  @override
  String toString() {
    return 'name=$name,age=$age,sex=$sex';
  }

  // 方法定义
  eat() {
    print('$name在吃东西');
  }

  /** setter和getter
   * 默认情况下,Dart中类定义的属性是可以直接被外界访问的
   * 但是某些情况下,我们希望监控这个类的属性被访问的过程,这个时候就可以使用setter和getter了
   */
  String get getName {
    return name;
  }
  set setName(String name) {
    this.name = name;
  }
}

class Person2 {
  final String name;

  /** 常量构造函数(一般只有一个)
   * 在某些情况下,传入相同值时,我们希望返回同一个对象,这个时候,可以使用常量构造方法
   * 使用identical(对象1, 对象2)函数来判断两个对象是否是同一个对象
   * 
   * 注意一:拥有常量构造方法的类中,所有的成员变量必须是final修饰的.
   * 注意二:为了可以通过常量构造方法,创建出相同的对象,不再使用 new 关键字,而是使用 const 关键字
   * 如果是将结果赋值给const修饰的标识符时,const可以省略
   */
  const Person2(this.name);
}

class Person3 {
  String name;
  int age;

  static final Map<String, Person3> _nameCache = {};

  /** 工厂构造函数
   * Dart提供了factory关键字, 用于通过工厂去获取对象
   */
  factory Person3.withName(String name) {
    if (_nameCache.containsKey(name)) {
      return _nameCache[name];
    } else {
      final p = Person3(name, age:28);
      _nameCache[name] = p;
      return p;
    }
  }

  Person3(this.name, {this.age = 18});
}

抽象类、类的继承

  • 一般来说抽象类不能实例化,但是有工厂构造函数的抽象类是可以被实例化的
  • 抽象类中的抽象方法必须被子类实现, 抽象类中已经被实现的方法, 可以不用子类重写,但是可以被重写
  • Dart中的继承使用extends关键字
  • 子类中使用super来访问父类
  • 父类中的所有成员变量和方法都会被继承,但是构造方法除外
main(List<String> args) {
  Dog d = Dog(null, 5);
  d.run();
}

/** 抽象类
 * 抽象类不能实例化
 * 抽象类中的抽象方法必须被子类实现, 抽象类中已经被实现的方法, 可以不用子类实现,但是可以被重写
 */
abstract class Animal {
  int age;

  Animal(this.age);

  /** 抽象方法
   * 抽象方法,必须存在于抽象类中。
   * 抽象类是使用abstract声明的类。
   */
  run();
}

/** 继承
 * Dart中的继承使用extends关键字
 * 子类中使用super来访问父类
 * 父类中的所有成员变量和方法都会被继承,,但是构造方法除外
 */
class Dog extends Animal {
  // 子类可以拥有自己的成员变量
  String name;

  /** 子类中可以调用父类的构造方法
   *    子类的构造方法在执行前,将隐含调用父类的无参默认构造方法(没有参数且与类同名的构造方法)。
   *    如果父类没有无参默认构造方法,则子类的构造方法必须在初始化列表中通过super【显式】调用父类的某个构造方法。
   */
  Dog(String name, int age) : name = name ?? "旺财", super(age);

  // 对父类的方法进行重写
  @override
  String toString() {
    return "name=$name,age=$age";
  }

  // 实现父类中的抽象方法
  @override
  run() {
    print('${name}在奔跑');
  }
}

隐式接口

  • Dart中没有哪一个关键字是来定义接口的
  • 默认情况下所有的类都是隐式接口
  • Dart只支持单继承
  • 当将一个类当做接口使用时, 那么实现这个接口的类, 必须实现这个接口中所有方法
  • 实现隐式接口使用implements关键字
main(List<String> args) {
  SuperMan m = SuperMan();
  m.flying();
}

/** 隐式接口
 * Dart中没有哪一个关键字是来定义接口的
 * 默认情况下所有的类都是隐式接口
 * Dart只支持单继承
 * 当将一个类当做接口使用时, 那么实现这个接口的类, 【必须实现】这个接口中【所有方法】
 * 实现隐式接口使用【implements】关键字
 */

class Runner {
  void running() {}
}

class Flyer {
  void flying() {}
}

abstract class Animal {
  void eating() {
    print("动物吃东西");
  }

  void running();
}

// 单继承
class SuperMan extends Animal implements Runner, Flyer {
  @override
  void running() {
    print("超人会奔跑");
  }

  @override
  void flying() {
    print("超人不仅能跑,还能飞");
  }
}

Mixin混入

  • 在通过implements实现某个类时,类中所有的方法必须被重新实现(无论这个类原来是否已经实现过该方法)
  • 这个在现实开发中不太现实,那么怎么解决这个问题呢?就是使用Mixin混入技术来实现
    • 除了可以通过class定义类之外,也可以通过mixin关键字来定义一个类
    • 只是通过mixin定义的类用于被其他类混入使用,通过with关键字来进行混入
main(List<String> args) {
  SuperMan m = SuperMan();
  m.running();
  m.flying();
}

/** 隐式接口
 * Dart中没有哪一个关键字是来定义接口的
 * 默认情况下所有的类都是隐式接口
 * Dart只支持单继承
 * 当将一个类当做接口使用时, 那么实现这个接口的类, 【必须实现】这个接口中【所有方法】
 * 实现隐式接口使用【implements】关键字
 */

mixin Runner {
  void running() {
    print("奔跑中...");
  }
}

mixin Flyer {
  void flying() {
    print("飞翔中...");
  }
}

abstract class Animal {
  void eating() {
    print("动物吃东西");
  }

  void running();
}

// 单继承,多混入
class SuperMan extends Animal with Runner, Flyer {

}

相关文章

网友评论

      本文标题:Flutter学习(四)Dart语法类和对象

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