Dart编程语言概览

2023-10-27

Dart编程语言概览

一个简单的Dart程序:

  • 注释,单行、多行
  • 数据类型、字面量、输出方式
  • 字符串插值
  • main()函数:特定的顶级函数
  • 定义变量var:通过这种方式定义变量不需要指定变量类型
// 定义一个函数
printInteger(int aNumber) {
   
  // 打印
  print('The number is $aNumber)');
}

// 应用从这里开始
main() {
   
  var number = 42;
  printInteger(number);
}

重要的概念:

  • 一切皆对象,所有对象都有对应的一个的实例;无论数字、函数和null都是对象;所有对象都继承自Object类;
  • Dart是强类型语言,但可以推断类型;如果要明确说明不需要任何类型,需要使用特殊类型dynamic动态类型;
  • Dart支持泛型,如List<int>整数列表、List<dynamic>任何类型的对象列表;
  • Dart对函数的支持:
    • 支持顶级函数main()
    • 绑定在类上——静态函数
    • 绑定在对象上——实例函数
    • 支持函数内创建函数(嵌套或 局部函数)
  • Dart对变量的支持:
    • 支持顶级变量
    • 绑定在类上——静态变量
    • 绑定在对象上——实例变量(字段/属性)
  • Dart没有关键字public/protected/private,如果标识符以下划线_开头,则它相对于库是私有的;
  • Dart表达式(运行时有值),语句(运行时无值);condition?expr1:expr2值可能是二者之一,if-else语句没有值;语句可以包含表达式,但是表达式不能直接包含语句;
  • Dart工具提示两种类型问题:警告 和 错误(编译时错误会阻止代码执行 或 运行时错误会导致代码在执行过程中引发异常);

Dart关键字解析:

  • abstract:定义 抽象类 — 抽象类不能实例化;抽象类通常用来定义接口,以及部分实现。 如果希望抽象类能够被实例化,那么可以通过定义一个 工厂构造函数 来实现;
// 这个类被定义为抽象类,
// 所以不能被实例化。
abstract class AbstractContainer {
   
  // 定义构造行数,字段,方法...

  void updateChildren(); // 抽象方法。
}
  • asasisis!运算符用于在运行时处理类型检查;
    • 例如, obj is Object 总是 true。 但是只有 obj 实现了 T 的接口时, obj is T 才是 true。
    • 使用 as 运算符将对象强制转换为特定类型;
if (emp is Person) {
   
  (emp as Person).firstName = 'Bob';
}
  • assert:如果 assert 语句中的布尔条件为 false , 那么正常的程序执行流程会被中断

    • 例如,assert(urlString.startsWith('https'), 'URL ($urlString) should start with "https".');
    • assert 语句只在开发环境中有效, 在生产环境是无效的;
    • 断言失败,会抛出异常 (AssertionError);
  • asyncawait

    • Dart 库中包含许多返回 Future 或 Stream 对象的函数. 这些函数在设置完耗时任务(例如 I/O 曹组)后, 就立即返回了,不会等待耗任务完成。 使用 async 和 await 关键字实现异步编程。 可以让你像编写同步代码一样实现异步操作。
    • 要使用 await , 代码必须在 异步函数(使用 async 标记的函数)中;
    • 使用 try, catch, 和 finally 来处理代码中使用 await 导致的错误。
    • 在一个异步函数中可以多次使用 await
    • 在 await 表达式 中, 表达式 的值通常是一个 Future 对象; 如果不是,这是表达式的值会被自动包装成一个 Future 对象。
Future checkVersion() async {
   
  var version = await lookUpVersion();
  // Do something with version
}

try {
   
  version = await lookUpVersion();
} catch (e) {
   
  // React to inability to look up the version
}

var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
  • breakcontinue
    • 使用 break 停止程序循环,使用 continue 跳转到下一次迭代;
    • 如果对象实现了 Iterable 接口 (例如,list 或者 set)。 那么示例完全可以用另一种方式来实现:
while (true) {
   
  if (shutDownRequested()) break;
  processIncomingRequests();
}

for (int i = 0; i < candidates.length; i++) {
   
  var candidate = candidates[i];
  if (candidate.yearsExperience < 5) {
   
    continue;
  }
  candidate.interview();
}

candidates
    .where((c) => c.yearsExperience >= 5)
    .forEach((c) => c.interview());
  • caseswitchdefault
    • 在Dart中switch语句使用==比较比较整数,字符串,或者编译时常量
    • 比较的对象必须都是同一个类的实例(并且不可以是子类), 类必须没有对 == 重写。
    • 枚举类型 可以用于 switch 语句
    • 在 case 语句中,每个非空的 case 语句结尾需要跟一个 break 语句;除 break 以外,还有可以使用 continue, throw,者 return。
    • Dart 支持空 case 语句, 允许程序以 fall-through 的形式执行。
    • 在非空 case 中实现 fall-through 形式, 可以使用 continue 语句结合 lable 的方式实现
    • case 语句可以拥有局部变量, 这些局部变量只能在这个语句的作用域中可见。
var command = 'OPEN';
switch (command) {
   
  case 'CLOSED':
    executeClosed();
    // break; // 缺省break会报错
  case 'PENDING':
    // executePending(); //但支持空case语句
    // break;
  case 'APPROVED':
    executeApproved();
    continue open;
  case 'DENIED':
    executeDenied();
    break;
  open:
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}
  • catchfinallyrethrow:捕获异常可以避免异常继续传递(除非重新抛出( rethrow )异常)。 可以通过捕获异常的机会来处理该异常
    • 通过指定多个 catch 语句,可以处理可能抛出多种类型异常的代码。
    • catch 语句未指定类型, 则该语句可以处理任何类型的抛出对象
    • catch() 函数可以指定1到2个参数, 第一个参数为抛出的异常对象, 第二个为堆栈信息 ( 一个 StackTrace 对象 )。
    • 如果仅需要部分处理异常, 那么可以使用关键字 rethrow 将异常重新抛出。
    • 不管是否抛出异常, finally 中的代码都会被执行。 如果 没有用catch 匹配异常, 异常会在 finally 执行完成后,再次被抛出;任何匹配的 catch 执行完成后,再执行 finally ;
try {
   
  breedMoreLlamas();
} on OutOfLlamasException {
   
  // 一个特殊的异常
  buyMoreLlamas();
} on Exception catch (e) {
   
  // 其他任何异常
  print('Unknown exception: $e');
} catch (e, s) {
   
  // 没有指定的类型,处理所有异常
  print('Something really unknown: $e');
  rethrow; 
} finally {
   
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}
  • throw
    • 高质量的生产环境代码通常会实现 ErrorException 类型的异常抛出
// 抛出异常
throw FormatException('Expected at least 1 section');

// 抛出任意对象
throw 'Out of llamas!';

// 因为抛出异常是一个表达式, 所以可以在 => 语句中使用,也可以在其他使用表达式的地方抛出异常:
void distanceTo(Point other) => throw UnimplementedError();

  • classthis:class 用于声明类;
    • 所有实例变量都生成隐式 getter 方法。 非 final 的实例变量同样会生成隐式 setter 方法
    • 构造函数中,使用 this 关键字引用当前实例;仅当存在命名冲突时,使用 this 关键字。 否则,按照 Dart 风格应该省略 this ;(通常模式下,会将构造函数传入的参数的值赋值给对应的实例变量)
class Point {
   
  num x; // 声明示例变量 x,初始值为 null 。
  num y; // 声明示例变量 y,初始值为 null 。
  num z = 0; // 声明示例变量 z,初始值为 0 。

  // 生成构造函数
  Point(num x, num y) {
   
    // 还有更好的方式来实现下面代码,敬请关注。
    this.x = x;
    this.y = y;
  }

}
  • constfinal
    • 使用过程中从来不会被修改的变量, 可以使用 final 或 const, 而不是 var 或者其他类型
    • Final 变量的值只能被设置一次;Const 变量在编译时就已经固定 (Const 变量 是隐式 Final 的类型.)
    • 实例变量可以是 final 类型但不能是 const 类型。
    • 如果 Const 变量是类级别的,需要标记为 static const
    • Const 关键字不仅可以用于声明常量变量,还可以用来创建常量值(const关键字在声明常量构造函数时还有应用,参考关键字new的描述)
// 声明常量变量
const bar = 1000000;
// 创建常量值
var foo = const [];
  • deferred
    • Deferred loading (也称之为 lazy loading) 可以让应用在需要的时候再加载库
    • 常用场景:减少 APP 的启动时间。执行 A/B 测试,例如 尝试各种算法的 不同实现。加载很少使用的功能,例如可选的屏幕和对话框。
    • 延迟加载库的常量在导入的时候是不可用的,在导入文件的时候也无法使用延迟库中的类型;
// 要延迟加载一个库,需要先使用 deferred as 来导入
import 'package:greetings/hello.dart' deferred as hello;

// 当需要使用的时候,使用库标识符调用 loadLibrary() 函数来加载库:
Future greet() async {
   
  // 可以多次调用 loadLibrary() 函数。但是该库只是载入一次
  await hello.loadLibrary();
  hello.printGreeting();
}
  • dodo-while
while (!isDone()) {
   
  doSomething();
}

do {
   
  printLine();
} while (!atEndOfPage());
  • dynamic:动态的数据类型
  • else if:和 JavaScript 不同, Dart 的判断条件必须是布尔值,不能是其他类型
if (isRaining()) {
   
  you.bringRainCoat();
} else if (isSnowing()) {
   
  you.wearJacket();
} else {
   
  car.putTopDown();
}

  • enum:枚举类型也称为 enumerations 或 enums , 是一种特殊的类,用于表示数量固定的常量值
    • 枚举中的每个值都有一个 index getter 方法, 该方法返回值所在枚举类型定义中的位置(从 0 开始)
    • 使用枚举的 values 常量, 获取所有枚举值列表( list )
    • 可以在 switch 语句 中使用枚举, 如果不处理所有枚举值,会收到警告
    • 枚举不能被子类化,混合或实现
    • 枚举不能被显式实例化
enum Color {
    red, green, blue }

assert(Color.red.index == 0);

List<Color> colors = Color.values;
assert(colors[2] == Color.blue);


  • export
    • 库代码位于lib目录下,对其他包是公开的。您可以根据需要在lib下创建任何层次结构。按照惯例,实现代码放在lib/src下。lib/src下的代码被认为是私有的;其他包永远不需要导入src/…要使lib/src下的api公开,可以从直接位于lib下的文件导出lib/src文件;
// 目录结构
- src
  - cascade.dart
  - ...
- shelf.dart
- shelf_io.dart


// shelf.dart, exports several files from lib/src:
export 'src/cascade.dart';
export ...

  • extendssuper:使用 extends 关键字来创建子类, 使用 super 关键字来引用父类
class Television {
   
  void turnOn() {
   
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
   
  void turnOn() {
   
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}
  • factory:工厂构造函数
    • 当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。
    • 一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。
    • 工厂构造函数无法访问 this。
class Logger {
   
  final String name;
  bool mute = false;

  // 从命名的 _ 可以知,
  // _cache 是私有属性。
  static final Map<String, Logger> _cache =
      <String, Logger>{
   };

  factory Logger(String name) {
   
    if (_cache.containsKey(name)) {
   
      return _cache[name];
    } else {
   
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

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

// 工厂构造函的调用方式与其他构造函数一样 
var logger = Logger('UI');
logger.log('Button clicked');

  • falsetrue
  • for
    • 闭包在 Dart 的 for 循环中会捕获循环的 index 索引值, 来避免 JavaScript 中常见的陷阱
    • 如果要迭代一个实现了 Iterable 接口的对象, 可以使用 forEach() 方法
    • 实现了 Iterable 的类(比如, List 和 Set)同样也支持使用 for-in 进行迭代操作 iteration
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
   
  message.write('!');
}


var callbacks = [];
for (var i = 0; i < 2; i++) {
   
  // 输出的是 0 和 1。 但是示例中的代码在 JavaScript 中会连续输出两个 2 
  callbacks.add(() => print(i));
}

// 如果不需要使用当前计数值, 使用 forEach() 是非常棒的选择;
callbacks.forEach((c) => c());

var collection = [0, 1, 2];
for (var x in collection) {
   
  print(x); // 0 1 2
}

  • Function

    • Dart 是一门真正面向对象的语言, 甚至其中的函数也是对象,并且有它的类型 Function;
    • 这也意味着函数可以被赋值给变量或者作为参数传递给其他函数。
    • 箭头 语法=> expr; 语法是 { return expr; } 的简写;
    • 在箭头 (=>) 和分号 (;) 之间只能使用一个 表达式 ,不能是 语句
    • 函数有两种参数类型: required 和 optional。 required 类型参数在参数最前面, 随后是 optional 类型参数。 命名的可选参数也可以标记为 “@required
    • 可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。
  • 命名参数 & 位置参数:

    • 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 null。
    • list 或 map 可以作为默认值传递;
// 位置参数声明方式
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
// 位置参数的调用方式
isNoble(100);

// 命名参数声明方式
void enableFlags({
   bool bold, bool hidden= false}) {
   ...}
// 命名参数的调用方式
enableFlags(bold: true, hidden: false);


// Flutter 创建实例的表达式可能很复杂, 因此窗口小部件构造函数仅使用命名参数
const Scrollbar({
   Key key, @required Widget child})

// 位置可选参数
String say(String from, String msg, [String device]) {
   
  var result = '$from says $msg';
  if (device != null) {
   
    result = '$result with a $device';
  }
  return result;
}

// list 或 map 可以作为默认值传递
void doStuff(
    {
   List<int> list = const [1, 2, 3],
    Map<String, String> gifts = const {
   
      'first': 'paper',
      'second': 'cotton',
      'third': 'leather'
    }}) {
   
  print('list:  $list');
  print('gifts: $gifts');
}

Required 被定义在 meta package。 无论是直接引入(import) package:meta/meta.dart ,或者引入了其他 package,而这个 package 输出(export)了 meta,比如 Flutter 的 package:flutter/material.dart

  • implements:隐式接口
    • 每个类都隐式的定义了一个接口,接口包含了该类所有的实例成员及其实现的接口。 如果要创建一个 A 类,A 要支持 B 类的 API ,但是不需要继承 B 的实现, 那么可以通过 A 实现 B 的接口。
    • 一个类可以通过 implements 关键字来实现一个或者多个接口, 并实现每个接口要求的 API。
// 一个类对应一个 隐式的接口Person
class Person {
   
  // 包含在接口里,但只在当前库中可见。
  final _name;

  // 不包含在接口里,因为这是一个构造函数。
  Person(this._name);

  // 包含在接口里。
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// person 接口的实现。
class Impostor implements Person {
   
  get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

// 调用
String greetBob(Person person) => person.greet('Bob');

void main() {
   
  print(greetBob(Person('Kathy')));
  print(greetBob(Impostor()));
}


// 实现多个接口
class Point implements Comparable, Location {
   ...}
  • getset
    • Getter 和 Setter 是用于对象属性读和写的特殊方法
    • 使用 get 和 set 关键字实现 Getter 和 Setter ,能够为实例创建额外的属性。
class Rectangle {
   
  num left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  // 定义两个计算属性: right 和 bottom。
  num get ri
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dart编程语言概览 的相关文章

随机推荐

  • 开关电源PFC电路原理详解及matlab仿真

    PFC全称 Power Factor Correction 意为 功率因数校正 PFC电路即能对功率因数进行校正 或者说能提高功率因数的电路 在电学中 功率因数PF指有功功率P 单位w 与视在功率S 单位VA 的比值 在初高中的电学中 我们
  • 计算机各外设的作用,计算机外设的功能是什么

    外部设备简称 外设 是指连在计算机主机以外的硬件设备 对数据和信息起着传输 转送和存储的作用 是计算机系统中的重要组成部分 随着我国计算机应用的迅速普及以及网络化 信息化应用的日益广泛 使市场对计算机外部设备的需求不断增长 从而拉动了我国计
  • 已知IP地址是192.168.5.121,子网掩码是255.255.255.248,试求网络地址和主机地址。...

    根据子网掩码的规则 将 IP 地址和子网掩码进行二进制 AND 操作 即可得到网络地址 IP 地址 11000000 10101000 00000101 01111001 192 168 5 121 子网掩码 11111111 111111
  • 负载均衡器技术Nginx和F5的优缺点对比

    nginx 一 nginx详解 nginx是一个被广泛使用的集群架构组件 我们有必要对它有足够的了解 下面将先认识nginx 包括应用场景 nginx基本架构 功能特性 并发模型以及配置说明 最后我们再总结下 为什么选择nginx的原因 1
  • 编译支付宝小程序 设置页面滚动时 overflow-y: auto不生效

    前言 由于公司业务调整 特意学习下uni项目框架 其实根据官方api就是实现很多功能 其实都是一些小坑 uni编译支付宝小程序 设置页面滚动时 overflow y auto不生效 解决 设置页面滚动时 不能设置overflow y aut
  • JavaScript教程-对象,文本和属性,方括号,计算属性,属性名称限制,in操作符,for..in,对象引用复制,深层克隆const修改

    对象 正如我们在 数据类型 一章学到的 JavaScript 中有八种数据类型 有七种原始类型 因为它们的值只包含一种东西 字符串 数字或者其他 相反 对象则用来存储键值对和更复杂的实体 在 JavaScript 中 对象几乎渗透到了这门编
  • 选择CentOS还是Ubuntu?

    Ubuntu和CentOS都是常见的Linux发行版 它们都有其优点和适用场景 Ubuntu是一种易于使用的操作系统 适合初学者 它具有良好的社区支持和广泛的软件库 因此很容易找到和安装需要的软件 Ubuntu还经常更新软件包 提供新功能和
  • UTXO介绍

    什么是UTXO 在比特币钱包当中 我们通常能够看到账户余额 然而在中本聪设计的比特币系统中 并没有余额这个概念 比特币余额 是由比特币钱包应用派生出来的产物 中本聪发明了UTXO交易模型 并将其应用到比特币当中 UTXO Unspent T
  • 怎样在html中写css样式,hbuilder的css怎么写

    HBuilder怎么查框架的css的属性 HBuilder在用框架时怎么查框架的css的属性 1 js中定义的变量和函数 在引用变量或函数时 可以跳转到定义的位置 包括HTML中同文件内部跳转及HTML向js文件的跳转 2 css中定义的样
  • Java开发工具JDK+IDEA+MySql+maven+tomact+sqlyong+postMan+redis+RMQ+node

    开发工具 JDK 1 8 含1 8中文API 链接 https pan baidu com s 1t43L4nxCqzmCIhKp JZvIg 提取码 9woy 开发工具 IDEA 含解密文档 链接 https pan baidu com
  • Unity普通项目升级为URP通用渲染管线(图文详解)

    Unity普通项目升级为URP通用渲染管线 前言 一 导入Universal RP 二 创建Pipeline Asset 三 设置Graphics 四 更改Rendering 五 素材升级URP 总结 版权声明 前言 我的unity版本是2
  • RASP解决Java安全问题探讨

    Java 语言在应用场景下有更健全的性能 对于很多企业而言是应用程序编写选择中的 Plan A 树大招风 这也使得它成为攻击者重点关注的对象 在软件开发的过程中 程序员通常会引入第三方库提高自己的研发效率 但开源代码的安全性和可靠性很难保证
  • 租用Topaz Video Enhance AI

    智星云算力平台已认证帐号在智星云租赁并使用Topaz Video Enhance AI 1 租用win10渲染镜像 2 设备管理器 查看显卡状态 3 安装 Topaz Video Enhance AI 软件 4 在 preferences
  • ATM(异步传输模式)是什么?

    异步传输模式 ATM 也称为信元中继 在固定大小的信元中传输数据 通过光纤或双绞线电缆 高速交换 在OSI模型的数据链路层 第2层 运行基于ITU T宽带综合业务数字网络 B ISDN 标准的网络技术 该标准是电信业开发的 自动取款机可以同
  • 【区块链论文整理】SIGMOD 篇 (二)

    SIGMOD Special Interest Group On Management Of Data 是数据库三大顶会之一 近几年也发表了不少水平很高的文章 本文主要针对SIGMOD会议中区块链相关的论文进行简单整理 ACM SIGMOD
  • 运算符之 --- 取余运算 %

    取模运算 javascript取模运算是一个表达式的值除以另一个表达式的值 并返回余数 取模在js里就是取余数的意思 a b 是求余数 a b 是求商 Math abs x 是求x的绝对值 12除以5 2 余数是2 即5 2 2 12 所以
  • C++:使用private继承

    在通常的程序设计中很少使用private继承 因为private继承其实相当于 根据某物实现 而这种情况应该通过类成员变量的方式来实现 那么private继承其实只有两个使用场景 1 需要重写虚函数 include
  • MobileSAM:更快的分割一切!面向移动端的轻量级SAM,比FastSAM快4倍!

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 点击进入 gt 图像分割和Transformer 交流群 转载自 极市平台 作者 happy 导读 本文提出一种 解耦蒸馏 方案对SAM的ViT H解码器进行蒸馏 同时
  • 从Inception v1,v2,v3,v4,RexNeXt到Xception再到MobileNets,ShuffleNet,MobileNetV2,ShuffleNetV2,MobileNetV3

    v1 Going deeper with convolutions Inception v1的网络 主要提出了Inceptionmodule结构 1 1 3 3 5 5的conv和3 3的pooling组合在一起 最大的亮点就是从NIN N
  • Dart编程语言概览

    Dart编程语言概览 一个简单的Dart程序 注释 单行 多行 数据类型 字面量 输出方式 字符串插值 main 函数 特定的顶级函数 定义变量var 通过这种方式定义变量不需要指定变量类型 定义一个函数 printInteger int