Dart | 浅析dart中库的导入与拆分

前言

最近十分热门的跨平台框架使用了一门比较生僻的编程语言dart。dart语言自己深受早期一些编程语言的影响。特别是Smalltalk,Java和JavaScript。我是从Java语言向dart过分的,一开始感受很不错,快速就对这门语言有了一个初步的认识,并可以写小段代码了。编程

但在flutter的不断学习过程当中,我遇到了很多由于dart的一些语法而产生的困惑。回过头来看dart的语法以后产生了一些顿悟,在此记录下来但愿能帮助到更多的学习者。json

你将学到什么

  • 外部库的彻底导入与不彻底导入
  • 导入新的库对变量命名空间的影响
  • 库的拆分——part

导入

彻底导入

咱们假定须要在A库里使用B库的某些方法,咱们须要将B库import进A库。这是咱们十分熟悉的。网络

import 'B.dart';
复制代码

不只如此,dart的导入语句还适用于任意url。咱们可使用网络上的某个资源(dart文件)做为外部库导入。框架

import 'http://hello/hello.dart';
复制代码

可是咱们不推荐这样作。由于网络资源随时可能会发生变化。一旦改变,咱们的程序将会被破坏。less

真正严谨的作法是:dom

import'package:hello/hello.dart';
复制代码

使用 package:导入方式会执行一个常驻的封装了代码位置信息的包管理器。编程语言

一个库可使用的所有对象包括这个库自己声明的,以及经过导入语句从其余库导入的。在dart:core中定义的对象是隐式导入的。而一个库对外可以使用的对象称为库导出的命名空间。ide

理论上一个库的命名空间中不该有名称相同的两个对象,不然你须要使用别名。学习

import 'test2.dart'
class Test{
    static final hello = new Test();
}
复制代码
class Test2{
    static final hello = new Test2();
    Test2 _test = new Test2();
}
复制代码

在这段代码中,Test2被import进了Test库,咱们在test库中是没法看到Test2的私有变量_test的,因此这个变量将不会被导入到命名空间。ui

在Dart中,当前库所声明的对象优先级高于任何对象,所以导入的库中有顶层对象并不会有想象中那样具备破坏性。可是若是你访问了一个导入的对象,另一个导入后续又添加了一个同名对象,那么新导入的对象会覆盖原有对象。

不彻底导入

Dart提供了额外的机制来控制导入到库内的对象:命名组合器show和hide。

show

当咱们只须要一个庞大库中某一个或某几个(少数)的对象的时候,咱们能够选择使用show组合器进行导入。这样可使你的库更加健壮。

import 'package:math' show Random;
复制代码

在这行代码中,咱们只导入了math库中的Random对象。

show组合器接收一个命名空间和一个标识符列表,并将标识符列表中出现的对象保留在命名空间。

hide

当咱们在一个库种但愿不导入某一个或某几个对象的时候,咱们可使用hide组合器进行导入。

import 'package:math' hide Random;
复制代码

这段代码将导入math库但不导入math库种的Random对象。实现方式与show相似。一样也是接收一个命名空间和标识符列表,并将标识符列表中出现的对象从命名空间中丢弃,而后产生一个新的命名空间。

解决变量名冲突的办法

解决此问题最好的办法是将引入的库加上别名。

import 'package:math' as mymath;
复制代码

经过这种方式咱们能够完美避开不一样库之间由于导入而使得变量名冲突的问题。

库的拆分

有的时候一个库可能太大,不能方便的保存在一个文件当中。Dart容许咱们把一个库拆分红一个或者多个较小的part组件。或者咱们想让某一些库共享它们的私有对象的时候,咱们须要使用part。

这里咱们能够看到,parttest2.dart是part of 'parttest.dart'的文件,能够理解为,parttest2是parttest的一部分。在part test2.dart中,咱们并无引入package:flutter/material.dart包就直接继承了StatelessWidget,是由于,在part中,import进来的库是共享命名空间的。

不是全部的库都有名称,但若是使用part来构建库,那么库必需要命名。

library xxx;
复制代码

每一个子part都存放在各自的文件中。可是它们共享同一做用域,库的内部命名空间,以及全部的导入(import)。

下面这个例子是在 Json 反序列化时使用到库的拆分。

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'data.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Data _$DataFromJson(Map<String, dynamic> json) {
  return Data(
      by: json['by'] as String,
      descendants: json['descendants'] as int,
      id: json['id'] as int,
      kids: (json['kids'] as List)?.map((e) => e as int)?.toList(),
      score: json['score'] as int,
      time: json['time'] as int,
      title: json['title'] as String,
      type: json['type'] as String,
      url: json['url'] as String);
}

Map<String, dynamic> _$DataToJson(Data instance) => <String, dynamic>{
      'by': instance.by,
      'descendants': instance.descendants,
      'id': instance.id,
      'kids': instance.kids,
      'score': instance.score,
      'time': instance.time,
      'title': instance.title,
      'type': instance.type,
      'url': instance.url
    };


复制代码

而后做为 data.dart 的一部分。

import 'package:json_annotation/json_annotation.dart';
part 'data.g.dart';

@JsonSerializable()
class Data{
  final String by;
  final int descendants;
  final int id;
  final List<int> kids;
  final int score;
  final int time;
  final String title;
  final String type;
  final String url;

  Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
    this.title, this.type, this.url});
//反序列化
  factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
//序列化
  Map<String, dynamic> toJson() => _$DataToJson(this);
}

复制代码

在上述例子中,咱们能够看到,part data.dart中Data类中调用了part data.g.dart的DataFromJson(json)方法,而第二个part中构建DataFromJson(json)方法返回Data对象并无在part data.g.dart定义。它们彼此之间是共用的命名空间。而且私有对象也是能够互相访问的。

part也能够经过url指明它所在的库,可是咱们一样也是不推荐这样作的。

Part与import有什么区别

可见性: 若是说在A库中import了B库,A库对B库是不可见的,也就是说B库是没法知道A库的存在的。而part的做用是将一个库拆分红较小的组件。两个或多个part共同构成了一个库,它们彼此之间是知道互相的存在的。

做用域:import不会彻底共享做用域,而part之间是彻底共享的。若是说在A库中import了B库,B库import了C库,A库是没有办法直接使用C库的对象的。而B,C如果A的part,那么三者共享全部对象。而且包含全部导入。

写在最后

以上就是Dart中库的导入与拆分的所有内容,如有描述不许确或错误之处欢迎各位大牛指正!

以后我会更新一系列flutter干货,若是你喜欢的话能够关注我或者给我一个好评哦!我会更新更有动力的。

相关文章
相关标签/搜索