[Flutter] dart: class;abstract class;factory;类、抽象类、工厂构造函数

一、缘起

JJ最近在在使用Flutter 重构以前Native项目时,对网络库dio 进行封装的时候发现Dio在实例的时候是 Dio对象时,无意中发现Dioclass 时抽象类,却还能使用Dio() 构造函数实例化,这是为什么呢?查看Flutter源码时集合对象ListMap 定义时都是abstract class 震惊!!! why?

源于factory 工厂构造函数。

二、关于dartclass 的声明

1.举个🌰

示例采用 官方文档 和文档描述,因文档和blog众多,此处不再赘述。

class Logger {
  final String name;
  bool mute = false;
  static final Map<String, Logger> _cache = <String, Logger>{};

  factory Logger(String name) {
    return _cache.putIfAbsent(name, () => Logger._internal(name));
  }

  factory Logger.fromJson(Map<String, Object> json) {
    return Logger(json['name'].toString());
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}

上述代码出现的factory会在下面一起描述

三、abstract class 抽象类

3.1 dart 中的抽象类不能实例化?

答案是肯定的,和其他语言一样抽象类是不能实例化.

那下面代码该如何解释呢?

 Map<String, dynamic> map = Map();

追踪一下Map的定义

// from: DartPackage/sky_engine/core/main.dart
...
/// Creates an empty [LinkedHashMap].
abstract class Map<K, V> {
  external factory Map();
  ...
}
  • Map 定义的修饰符是abstract,为什么可以通过构造函数实例化?
  • Map类似的还有List, 此处以Map为例
  • 此处的externalfacotry 又是啥意思,是他们影响的吗?顺着这个线索我们去一探究竟。

3.2 刨根问底

3.2.1 external

9.4 External Functions externalFunctions
An external function is a function whose body is provided separately from its
declaration. An external function may be a top-level function (19), a method
(10.2, 10.8), a getter (10.3), a setter (10.4), or a non-redirecting constructor
(10.7.1, 10.7.2). External functions are introduced via the built-in identifier
external (17.38) followed by the function signature.
文档索引

JJ的理解:external:编译标识,关键字主要作用是:将声明和实现分开。external 函数呢可能是一个顶级函数,或者方法,或者一个getter, 一个setter 又或者非重定向的构造函数。巴拉巴拉这么多,表明这个关键字是用来定义声明的。后面呢主要是说明,是用来解决 dart.vm在浏览器和客户端和服务端平台的不同实现而引入的。我这个又是废话了,嗯,那我们来顺着这个线索来找一下这个Mapbody(实现)!

3.2.1 body

根据线索,我们知道了,Map() 创建了一个/// Creates an empty [LinkedHashMap]. 然后我们就从
LinkedHashMap 入手,还有文档提供的这是关于dart.vm来的,所以只能去瞅瞅sdk 了。IDE 打开sdk 全局搜索吧。

LinkedHashMap实现
万幸搜索的结果不是很多,就一个一个的去看吧,先到第一个文件中去看。篇幅有限,只截取代码片段,

@patch
class LinkedHashMap<K, V> {
  @patch
  factory LinkedHashMap(
     ...
    if (isValidKey == null) {
      if (hashCode == null) {
        if (equals == null) {
          return new _InternalLinkedHashMap<K, V>();
        }
        hashCode = _defaultHashCode;
      } else {
        if (identical(identityHashCode, hashCode) &&
            identical(identical, equals)) {
          return new _CompactLinkedIdentityHashMap<K, V>();
        }
        ...
  • 此处我们知道了,LinkedHashMap 是返回了_InternalLinkedHashMap_CompactLinkedIdentityHashMap 对象。
3.2.2 @Path 为何物?

path的主要功能是和external 关联的注解。

3.2.3 最终的搜索范围缩小到上述的两个对象

目录为 ur flutter sdk path/bin/cache/dart-sdk/lib/_internal/vm/bin/compact_hash.dart

// VM-internalized implementation of a default-constructed LinkedHashMap.
@pragma("vm:entry-point")
class _InternalLinkedHashMap<K, V> extends _HashVMBase
    with
        MapMixin<K, V>,
        _HashBase,
        _OperatorEqualsAndHashCode,
        _LinkedHashMapMixin<K, V>
    implements LinkedHashMap<K, V> {
  _InternalLinkedHashMap() {
    _index = _uninitializedIndex;
    _hashMask = _HashBase._UNINITIALIZED_HASH_MASK;
    _data = _uninitializedData;
    _usedData = 0;
    _deletedKeys = 0;
  }
  • 由此可以说明: abstract抽象类中 factory 构造函数返回的instance实例,是来自于实现类(暂且将abstract 类看作interfacedart中并不包含interface 关键字).
3.2.4 _CompactLinkedIdentityHashMap

探索过程同理.

3.3 总结

3.3.1抽象类实构造函数实例化的原因

由于抽象类factory 工厂构造函数的作用,返回了实现类实例的实例。

官方文档描述的:factory构造函数中返回instance实例并不是都是从本实现类创建新的,可能来自于缓存,也就是章节二中表示的;也可能来自于子类。

3.3.2待研究场景
  • factory 用于单例模式的创建。
class Person {
	  
  factory Person() => _instance;

  Person._internal();
  
  static final Person _instance = Person._internal();

}
  • Dio中的思路

dio 库代码Dio 的设计思路。

  1. 此处工厂构造函数的实例对象类型有两个DioForBrowser,DioForNative
  2. 为了移动端网页端的支持用了比较巧妙的入口判断详情请参考注释部分
  3. 多端支持的实例化来来自于此dart-clang-issue;
...
//	入口判断代码
import 'entry_stub.dart'
    if (dart.library.html) 'entry/dio_for_browser.dart'
    if (dart.library.io) 'entry/dio_for_native.dart';
abstract class Dio {
  factory Dio([BaseOptions? options]) => createDio(options);
  ....
}

logs

  • jeversonjee 22.07.02 3.3.4.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值