Dart学习4

52 阅读1分钟

继承

实现继承

class Phone {
  void startup() {
    print('开机');
  }
  void shutdown() {
    print('关机');
  }
}

class AndroidPhone extends Phone {
}

void main() {
  var p = AndroidPhone();
  p.startup();
  p.shutdown();
}

开机
关机

父类调用

class Phone {
  void startup() {
    print('开机');
  }

  void shutdown() {
    print('关机');
  }
}

class AndroidPhone extends Phone {
  @override
  void startup() {
    super.startup();
    print('AndroidPhone 开机');
  }
}

void main() {
  var p = AndroidPhone();
  p.startup();
}

开机
AndroidPhone 开机

super 对象可以访问父类

调用父类构造

class Mobile {
  int number;
  Mobile(this.number);
  void showNumber() {
    print('010-$number');
  }
}

class AndroidPhone extends Mobile {
  AndroidPhone(int number) : super(number);
}

void main() {
  var p = AndroidPhone(12345678);
  p.showNumber();
}

010-12345678

可调用父类的 构造函数

重写超类函数

class Mobile {
  int number;
  Mobile(this.number);
}

class AndroidPhone extends Mobile {
  AndroidPhone(int number) : super(number);

  @override
  void noSuchMethod(Invocation mirror) {
    print('被重写 noSuchMethod');
  }
}

void main() {
  dynamic p = AndroidPhone(12345678);
  p.showNumber111();
}

被重写 noSuchMethod

在重写的函数上加修饰符 @override

继承抽象类的问题

abstract class IPhone {
  void startup() {
    print('开机');
  }

  void shutdown();
}

class AndroidPhone extends IPhone {
  @override
  void startup() {
    super.startup();
    print('AndroidPhone 开机');
  }

  @override
  void shutdown() {
    print('AndroidPhone 关机');
  }
}

void main() {
  var p = AndroidPhone();
  p.startup();
  p.shutdown();
}

开机
AndroidPhone 开机
AndroidPhone 关机

抽象类中只定义抽象函数,实例化访问会报错

多继承

多继承 with

  • 定义类
class Phone {
  void call() {
    print('Phone is calling...');
  }
}

class Android {
  void playStore() {
    print('Google play store');
  }
}

class Ios {
  void appleStore() {
    print('Apply store');
  }
}
  • with 混入
class Xiaomi with Phone, Android, Ios {}

采用 with ... , .... , ... 方式 mixin 入多个类功能

  • 执行
void main(List<String> args) {
  var p = Xiaomi();
  p.call();
  p.playStore();
  p.appleStore();
}

Phone is calling...
Google play store
Apply store

函数重名冲突

  • Android Ios 加入 call 函数
class Android {
  void playStore() {
    print('Google play store');
  }

  void call() {
    print('Android phone is calling...');
  }
}

class Ios {
  void appleStore() {
    print('Apply store');
  }

  void call() {
    print('Ios phone is calling...');
  }
}
  • 执行
void main(List<String> args) {
  var p = Xiaomi();
  p.call();
  p.playStore();
  p.appleStore();
}

Ios phone is calling...
Google play store
Apply store

可以发现后面的覆盖了前面的内容

mixin 不能构造函数

  • 加入构造函数
class Android {
  Android();
  ...
}

The class 'Android' can't be used as a mixin because it declares a constructor.
  • 加入 mixin 关键字 限定
mixin Android {
  // mixin 中不能定义 constructor
  ...
}

mixin on 限定条件

  • 关键字 on 限定 Phone
mixin Android on Phone {
  void playStore() {
    print('Google play store');
  }

  @override
  void call() {
    super.call();
    print('Android phone is calling...');
  }
}
  • with 混入时候,必须先 Phone 才行

错误

class Xiaomi with Android {}

'Android' can't be mixed onto 'Object' because 'Object' doesn't implement 'Phone'.
Try extending the class 'Android'.

正确

class Xiaomi with Phone,Android {}

工厂函数

调用子类

abstract class Phone {
  void call();
  factory Phone(String type) {
    switch (type) {
      case "android":
        return Android();
      case "ios":
        return Ios();
      default:
        throw "The '$type' is not an animal";
    }
  }
}

class Android implements Phone {
  @override
  void call() {
    print('Android Calling...');
  }
}

class Ios implements Phone {
  @override
  void call() {
    print('Ios Calling...');
  }
}

void main() {
  var android = Phone('android');
  var ios = Phone('ios');
  android.call();
  ios.call();
}

单例模式

class Phone {
  static final Phone _single = Phone._internal();
  Phone._internal();

  factory Phone() {
    return _single;
  }

  void call() {
    print('Calling...');
  }
}

void main() {
  var p1 = Phone();
  var p2 = Phone();
  print(identical(p1, p2));

  Phone().call();
}

减少重复实例对象

class Phone {
  int _number;
  Phone(this._number);

  factory Phone.fromJson(Map<String, dynamic> json) =>
      Phone(json['number'] as int);

  void call() {
    print('Calling $_number...');
  }
}

void main() {
  var p = Phone.fromJson({"number": 911});
  p.call();
}

如果不用工厂函数,就要用类静态方法,这样会有多余的实例对象

库 lib

导入核心库

import 'dart:io';

void main() {
  var f = new File('README.md');
  var content = f.readAsStringSync();
  print(content);
}

# Dart 语言学习示例

导入第三方库

  • 编写 pubspec.yaml
dependencies:
  dio: ^4.0.6
  • 执行拉取包命令
$ dart pub get
  • 程序调用
import 'package:dio/dio.dart';

void main() async {
  Dio dio = Dio();
  Response<String> response =
      await dio.get("https://wpapi.ducafecat.tech/products/categories");
  print(response.data);
}

[{"id":34,"name":"Bag","slug":"bag","parent":0,"description":" ......

导入自己的 git 仓库

  • 编写 pubspec.yaml
dependencies:
  uuid:
    git:
      url: https://github.com/Daegalus/dart-uuid
      ref: master
  • 执行拉取包命令
$ dart pub get

从 master 分支拉取

导入类文件

  • phone.dart
class Phone {
  void call() {
    print('Phone is calling...');
  }
}

class Android {
  void playStore() {
    print('Google play store');
  }

  void call() {
    print('Android phone is calling...');
  }
}

class Ios {
  void appleStore() {
    print('Apply store');
  }

  void call() {
    print('Ios phone is calling...');
  }
}
  • 实例
import 'package:dart_learn/phone.dart';

void main() {
  var p = Phone();
  p.call();
}

Phone is calling...

前缀&别名

import 'package:dart_learn/phone.dart' as pp;

void main() {
  var p = pp.Android();
  p.call();
  p.playStore();
}

Android phone is calling...
Google play store

筛选包内容

import 'package:dart_learn/phone.dart' show Ios;

void main() {
  var p = Ios();
  p.call();
  p.appleStore();
}

Ios phone is calling...
Apply store

hide 筛掉某几个包 show 只使用某几个包

延迟载入

import 'package:dart_learn/phone.dart' deferred as pp;

Future<void> main() async {
  await pp.loadLibrary();
  var p = pp.Android();
  p.call();
  p.playStore();
}

Android phone is calling...
Google play store

loadLibrary() 方式在需要的时候载入包 可提高程序启动速度 用在不常使用的功能 用在载入时间过长的包

泛型 generics

泛型使用

main(List<String> args) {
  var l = <String>[];
  l.add('aaa');
  l.add('bbb');
  l.add('ccc');
  print(l);

  var m = <int, String>{};
  m[1] = 'aaaa';
  m[2] = 'bbbb';
  m[3] = 'cccc';
  print(m);
}

[aaa, bbb, ccc]
{1: aaaa, 2: bbbb, 3: cccc}

容器对象,在创建对象时都可以定义泛型类型。

泛型函数

K addCache<K, V>(K key, V val) {
  print('$key -> $val');
  return val;
}

main(List<String> args) {
  var key = addCache('url', 'https://wiki.doucafecat.tech');
  print(key);
}

url -> https://wiki.doucafecat.tech
https://wiki.doucafecat.tech

构造函数泛型

class Phone<T> {
  final T mobileNumber;
  Phone(this.mobileNumber);
}

main(List<String> args) {
  var p = Phone<String>('ducafecat');
  print(p.mobileNumber);
}

这是大多数情况下使用泛型的场景,在一个类的构造函数中

泛型限制

  • 定义
class AndroidPhone {
  void startup() {
    print('Android Phone 开机');
  }
}

class Phone<T extends AndroidPhone> {
  final T mobile;
  Phone(this.mobile);
}
  • 实例
main(List<String> args) {
  var ad = AndroidPhone();
  var p = Phone<AndroidPhone>(ad);
  p.mobile.startup();
}

Android Phone 开机

通过 extends 关键字 可以限定你可以泛型使用的类型