IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [Flutter] dart: class;abstract class;factory;类、抽象类、工厂构造函数 -> 正文阅读

[移动开发][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.
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:36:33  更:2022-07-05 23:36:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 3:03:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码