Dart 语法学习笔记一


Dart 是谷歌于2011年10月10日发布一门开源编程语言(日子挑的不错)。2018年之前一直处于蛰伏状态,flutter 之后声名雀起,一发不可收拾!

Dart 的存在的存在的意义是什么呢?看一下官网的概述:

Dart is a client-optimized language for developing fast apps on any platform. Its goal is to offer the most productive programming language for multi-platform development, paired with a flexible execution runtime platform for app frameworks.

废话说完了,进入正题!

Hello Dart

怎么能少得了 Hello World !

// 程序入口函数
void main() {
  // 函数调用
  printHelloWorld();
}

// 定义函数 printHelloWorld
void printHelloWorld() {
 // 实现,打印 Hello World
  print("Hello World !");
}

如上,一个简单的 Hello World 就写完了。可以自己打开 DartPad 进行练手!
Dart 语法学习的过程中均可在其上进行练习,灰常方便!

Dart 语言特点

Dart 语言具有以下特点:
0、编译型;
1、强类型(Dart 2 才是);
2、面向对象,一切皆对象,数字、函数、null 都是对象;

语法

变量
使用关键字 var 进行变量的声明。

// 声明一个字符串变量 name 并赋值 Yuri
var  name = "Yuri";
// 声明一个变量 temperature 并赋值 35.0
var temperature = 35.0;

由于 Dart 有类型推断机制,name 会被自动判断为 String 类型。
也可以使用类型显式的声明一个变量:

String name = "Yuri";
double temperature = 28.5;

还可以使用 dynamicObject 声明一个变量。dynamicObject 的变量可以在后期改变赋值的类型,而 Var 声明的变量则不可以。 dynamic 这个特性与 Objective-C 中的 id 作用很像. dynamic 的这个特点使得我们在使用它时格外需要注意,因为很容易引入运行时错误。

dynamic name = "Yuri";
Object temperature = 28.5;
print("$name, $temperature");
// 打印结果:Yuri, 28.5

name = 28.5;
temperature = "Yuri";
print("$name, $temperature");
// 打印结果:28.5, Yuri

常量
使用关键字 finalconst 声明一个常量。

// 使用 final 声明一个 sex 的常量
final sex = "male";
// 使用 const 声明一个 nickName 的常量
const nickName = "Kitty";

使用 finalConst 声明的常量的值不能被修改。

finalconst 的区别在哪呢?
const 定义的常量在编译时就已经固定,final 定义的常量则在第一次使用时才被初始化。

Dart 内建类型

Number
Number 有两种类型 intdouble

// 定义一个 int 类型变量
int x = 1;
// 定义一个 double 类型变量
double y = 3.14;

int 整数值不大于64位, 具体取决于平台。 在 Dart VM 上, 值的范围从 -263 到 263 - 1. Dart 被编译为 JavaScript 时,使用 JavaScript numbers, 值的范围从 -253 到 253 - 1.
double: 64位(双精度)浮点数,依据 IEEE 754 标准。

String
Dart 字符串是一组 UTF-16 单元序列。字符串通过单引号双引号创建。

var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";

字符串可以通过${expression} 的方式内嵌表达式。 如果表达式是一个标识符,则{} 可以省略。

var s = 'string interpolation';
print("Dart has $s, which is very handy.");

在 Dart 中通过调用就对象的 toString() 方法来得到对象相应的字符串。

String oneAsString = 1.toString();
assert(oneAsString == '1');

String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

可以使用 + 运算符来把多个字符串连接为一个,也可以把多个字面量字符串写在一起来实现字符串连接。

var s1 = 'String '
    'concatenation'
    " works even over line breaks.";
print(s1);
// 打印结果: String concatenation works even over line breaks.

var s2 = 'The + operator ' + 'works, as well.';
print(s2);
// 打印结果:The + operator works, as well.

Boolean
bool,表示布尔值,有 truefalse 两个值。

bool isSunny = true;
bool isRainy = false;

List (也被称为 Array)
List 表示有序集合。

// 定义一个 整形 的数组字面量
var list = [1, 2, 3];

// 获取数组长度
var length = list.length;

// 访问数组元素. List 元素的下标也是从 0 开始的
var secondValue = list[1];

Map
通常来说, Map 是用来关联 keys 和 values 的对象。

var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

也可以使用 Map 的构造函数创建对象。

var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';

向 Map 添加一个 key-value

gifts["sixth"] = "cake";

访问 Map 中的 value

var sixthGift = gifts["sixth"];
assert(sixthGift == "cake");

Set
Set 表示无序元素的集合,集合内元素唯一。

var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

创建一个空集

var names = <String>{};

向 set 中添加元素

names.add("1");
names.addAll({"2", "3"});

Rune (用于在字符串中表示 Unicode 字符)
Dart 字符串是一系列 UTF-16 编码单元,即每个字符占 16 位, 而 Unicode 则是 32 位的,因此 Dart 字符串中表示 32 位 Unicode 值需要特殊语法支持。

Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(new String.fromCharCodes(input));

Symbol
一个 Symbol 对象表示 Dart 程序中声明的运算符或者标识符。 你也许永远都不需要使用 Symbol ,但要按名称引用标识符的 API 时, Symbol 就非常有用了。 因为代码压缩后会改变标识符的名称,但不会改变标识符的符号。 通过字面量 Symbol ,也就是标识符前面添加一个 # 号,来获取标识符的 Symbol 。

#radix
#bar

Symbol 字面量是编译时常量。

函数

Dart 中一切皆对象。函数也是对象,其对应的类型为 Function

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

在 Effective Dart 中推荐 公共API中声明类型, 但是省略了类型声明,函数依旧是可以正常使用的

isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

如果函数中只有一句表达式,可以使用简写语法:

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

=> expr 语法是 { return expr; } 的简写。 => 符号 有时也被称为 箭头 语法。

在 Dart 语言中,函数是一等对象(难道还有二等,三等?)。
函数可以作为另一个函数的参数,同时也可以把函数赋值给一个变量。

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];
// 将 printElement 函数作为参数传递。
list.forEach(printElement);

// 将函数作为值赋给变量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

匿名函数
一般情况下函数是有名字的,把没有名字的函数叫做匿名函数
匿名函数有时也被称为 lambda 或者 closure
在将函数作为值赋值给变量时,我们用的就是一个匿名函数。

可选参数
可选参数分命名参数位置参数。一个参数只能选择其中一种进行修饰。

命名可选参数

/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {
  ...
}

调用

enableFlags(bold: true, hidden: false);

命名可选参数可以用 @required 进行修饰,表示在函数调用时该参数不可缺少。

const Scrollbar({Key key, @required Widget child})

此时 Scrollbar 是一个构造函数, 当 child 参数缺少时,分析器会提示错误。

位置可选参数
将参数放到 [] 中来标记参数是可选的

String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

默认参数
在定义函数时,我们可以给参数一个默认值。

/// 设置 [bold] 和 [hidden] 标志 ...
void enableFlags({bool bold = false, bool hidden = false}) {
  ...
}

// bold 值为 true; hidden 值为 false.
enableFlags(bold: true);

运算符

算术运算符

操作符 功能
+
-
*
/
~/ 除法取整
% 模(余数)

除了上面的基本的算术运算符,Dart 同样也支持带有前缀的自增和自减运算符。
++exprexpr++--exprexpr--

/// 基本操作运算符示例
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 结果是双浮点型
assert(5 ~/ 2 == 2); // 结果是整型
assert(5 % 2 == 1); // 余数

/// 自增自减运算符示例
var a, b;

a = 0;
b = ++a; // a自加后赋值给b。
assert(a == b); // 1 == 1

a = 0;
b = a++; // a先赋值给b后,a自加。
assert(a != b); // 1 != 0

a = 0;
b = --a; // a自减后赋值给b。
assert(a == b); // -1 == -1

a = 0;
b = a--; // a先赋值给b后,a自减。
assert(a != b); // -1 != 0

关系运算符

操作符 功能
== 等于
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于

比较简单,不再示例。

类型判定运算符

操作符 功能
as 类型转化
is 类型判断(True if the object has the specified type)
is! 类型判断(False if the object has the specified type)

is 比较好理解,是就返回 true,不是就返回 false;
is! 意义则相反,不是就返回 true,是就返回 false;
个人感觉大部分情况下,is 就够了!

赋值运算符

= 是基本的赋值运算符,通过与其它操作符的组合,会产生许多其它的复合赋值运算符。如下

= -= /= %= >>= ^=
+= *= ~/= <<= &= |=

比较简单,不再示例。

逻辑运算符

操作符 含义
&&
||
!

不再示例。

按位和移位运算符

操作符 含义
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
~expr 取反(Unary bitwise complement (0s become 1s; 1s become 0s))
<< 左移(Shift left)
>> 右移(Shift right)

条件表达式

condition ? expr1 : expr2
如果条件为 true, 执行 expr1 (并返回它的值): 否则, 执行并返回 expr2 的值。

var visibility = isPublic ? 'public' : 'private';

expr1 ?? expr2
如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。

String playerName(String name) => name ?? 'Guest';

级联运算符

级联运算符 .. 可以实现对同一个对像进行一系列的操作。除了调用函数, 还可以访问同一对象上的字段属性。

querySelector('#confirm') // 获取对象。
  ..text = 'Confirm' // 调用成员变量。
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

这个运算符在 iOS 开发过程中没有遇到过,应该是 Dart 特胡的语法糖。

其它运算符

Operator Name Meaning
() Function application Represents a function call
[] List access Refers to the value at the specified index in the list
. Member access Refers to a property of an expression; example: foo.bar selects property bar from expression foo
?. Conditional member access Like ., but the leftmost operand can be null; example: foo?.bar selects property bar from expression foo unless foo is null (in which case the value of foo?.bar is null)

控制流程语句

if ... else ...

注意:条件语句必须是布尔值

if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

for loops

var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
  message.write('!');
}

while and do-while loops

while (!isDone()) {
  doSomething();
}

do {
  printLine();
} while (!atEndOfPage());

break and continue

break: 停止程序循环。
continue:跳过当次循环。

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();
}

switch and case

注意:正常情况下,case 中的 break 不可省略。

var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'PENDING':
    executePending();
    break;
  case 'APPROVED':
    executeApproved();
    break;
  case 'DENIED':
    executeDenied();
    break;
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}

assert

如果 assert 语句中的布尔条件为 false , 那么正常的程序执行流程会被中断。

// 确认变量值不为空。
assert(text != null);

// 确认变量值小于100。
assert(number < 100);

// 确认 URL 是否是 https 类型。
assert(urlString.startsWith('https'));

异常处理

Dart 可以抛出和捕获异常。
throw
throw 用于抛出异常。
当函数执行过程中出现了异常,可以通过 throw 将异常抛出。异常可以是 Exception 或 Error,或其它任何非 null 对象。当抛出异常时,程序也将会被终止。

throw FormatException('Expected at least 1 section');

以下示例抛出了一条字符串消息

throw 'Out of llamas!';

catch
捕获异常可以避免异常继续传递.

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  buyMoreLlamas();
}

通过指定多个 catch 语句,可以处理可能抛出多种类型异常的代码。 与抛出异常类型匹配的第一个 catch 语句处理异常。 如果 catch 语句未指定类型, 则该语句可以处理任何类型的抛出对象:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 一个特殊的异常
  buyMoreLlamas();
} on Exception catch (e) {
  // 其他任何异常
  print('Unknown exception: $e');
} catch (e) {
  // 没有指定的类型,处理所有异常
  print('Something really unknown: $e');
}

如上述代码所示,捕获语句中可以同时使用 oncatch ,也可以单独分开使用。 使用 on 来指定异常类型, 使用 catch 来 捕获异常对象。

catch() 函数可以指定1到2个参数, 第一个参数为抛出的异常对象, 第二个为堆栈信息 ( 一个 StackTrace 对象 )。

try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}

如果仅需要部分处理异常, 那么可以使用关键字 rethrow 将异常重新抛出。

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // Runtime error
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // Allow callers to see the exception.
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

finally
不管是否抛出异常, finally 中的代码都会被执行。 如果 catch 没有匹配到异常, 异常会在 finally 执行完成后,再次被抛出:

try {
  breedMoreLlamas();
} finally {
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}

任何匹配的 catch 执行完成后,再执行 finally :

try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // Handle the exception first.
} finally {
  cleanLlamaStalls(); // Then clean up.
}

Dart 语法学习笔记二

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345