-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dart #47
Comments
简介
main() {
print('hello world');
}
动机
设计准则万物皆对象
面向接口编程, 而非面向实现
Dart却力图通过以下几种方式来维护这个原则
类型是为开发者服务的
Dart 是一门类型可选的语言,
限制
概述
3
3 + 4
(3+4}*6
1 + 2 * 2
1234567890987654321 * 1234567890987654321
3.14159 //一个浮点数
'a string'
"another string - both double quoted and single quoted forms are supported"
'Hello World' //你已经见过它
true
false// 所有的布尔值都在这里
[] //一个空的列表
(0, 1.0, false, 'a', [2, 2.0, true, \b"]] //有5 个元素的列表,最后一个也是列表
[1, 2, 3] [1]
[1, 2, 3].length; // 3
[].length; // 0
[].isEmpty; // true
['a'].isEmpty; // false
main() {
print ('Hello World');
}
twice(x) => x * 2;
twice(2)
twice(x) {
return x * 2;
}
max(x, y) {
if (x > y)
return x;
else
return y;
}
max(x, y) => (x > y) ? x : y;
maxElement(a) {
var currentMax =
a.isEmpty ? throw 'Maximal element undefined for empty array' : a[0];
for (var i = 0; i < a.length; i++) {
currentMax = max(a[i], currentMax);
return currentMax;
}
}
class Point {
var x, y;
Point(a, b) {
x = a;
y = b;
}
}
var origin= new Point(0, 0);
var aPoint = new Point(3, 4);
var anotherPoint = new Point(3, 4);
origin.x // 0
origin.y // 0
aPoint.x // 3
aPoint.y // 4
class Point {
var x, y;
Point(this.x, this.y);
}
class Point {
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
}
aPoint.scale(2).x // 6
anotherPoint.scale(10).y // 40
class Point {
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
operator +(p) => new Point(x + p.x, y + p.y);
}
var temp = (aPoint + anotherPoint).y; // 8
import 'dart:math';
class A {
static distance(pl, p2) {
var dx = pl.x - p2.x;
var dy = pl.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
}
library points;
import 'dart:math';
class Point {
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
operator +(p) => new Point(x + p.x, y + p.y);
static distance(pl, p2) {
var dx = pl.x - p2.x;
var dy = pl.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
}
相关语言及其对Dart 的影响
|
库
main() {
print('hello world');
}
顶层
-个实现了栈的库library stack1;
final _contents = [];
get isEmpty => _contents.isEmpty;
get top => isEmpty ? throw 'Cannot get top of empty stack' : _contents.last;
get pop => isEmpty ? throw 'Cannot pop empty stack' : _contents.removeLast();
push(e) {
_contents.add(e);
return e;
}
脚本
隐私
class CachingClass {
var _cache;
operator [](i) {
if (_cache[i] == null) {
_cache[i] = complicatedFunction(i);
}
return _cache[i];
}
}
导入
import 'stack1.dart';
main() {
push('gently');
push('harder');
print(pop);
print(top);
}
package:
dart:
命名空间库内可用的对象
命名空间:提供给客户的对象
导入有冲突的变量
import 'package:stack1.dart';
import 'package:stack2.dart';
main() {}
import 'package:stack1.dart';
import 'package:stack2.dart';
main() {
//测试stack1
push('gently'); //静态警告
push('harder'); //静态警告
print(pop); //静态警告
print(top); //静态警告
//测试stack2
push('gently');
///静态警告
push('harder'); //静态警告
print(pop); //静态警告
print(top); //静态警告
}
为导入提供不同的前缀来进行区分
//import 'package:stack1.dart' as stack1;
//import 'package:stack2.dart' as stack2;
import 'stack1.dart' as stack1;
import 'stack2.dart' as stack2;
main() {
//测试stack1
stack1.push('gently'); //静态警告
stack1.push('harder'); //静态警告
print(stack1.pop); //静态警告
print(stack1.top); //静态警告
//测试stack2
stack2.push('gently');
///静态警告
stack2.push('harder'); //静态警告
print(stack2.pop); //静态警告
print(stack2.top); //静态警告
}
命名空间组合器show 和hide
hide 组合器
library lib1;
import 'stack1.dart' hide isEmpty, top;
show 组合器
library lib1;
import 'stack1.dart' show pop, push; 何时使用show, hide
如果真的想使自己的库健壮,那么你应该组合使用前缀和show, 只导入你实际使用的元素:library lib1;
impert 'stack1.dart' as stack1 show pop, push;
将库拆分成part
假设有一个库实现了一个Dart 的集成开发环境(IDE)
library ide;
import 'dart:io' as io;
import 'dart:rnirrors' as mirrors;
import 'dart:async' as async;
//还有更多:如UI 等.
part 'browsing.dart';
part 'inspecting.dart';
part 'debugging.dart';
part 'unitTestintegra巨on.dart';
part 'packages.dart';
part 'vcs.dart';
part 是结构化的,每个part 都必须以一个part 头来指定它属于哪一个库。
part of ide;
//顶层声明
class ClassBrowser{
}
导出IDE 例子
library ideAPI;
export 'browsing.dart' show AbstractBrowser, LibraryBrowser, ClassBrowser;
export 'inspecting.dart' show Objectlnspector;
export 'debugging.dart' show ThreadBrowser, ActivationBrowser;
export 'unitTestintegration.dart' show TestBrowser, TestSuite;
export 'packages.dart' show PackageBrowser;
export 'vcs.dart' show RepositoryBrowser; 导出指令 export
导出与导入完全独立
导出的规则与导入、part 的规则相同
钻石导入
延迟加载
延迟加载 deferredimport 'rarelyUsed.dart' deferred as rarelyUsed;
显示地加载 loadLibrary()
rarelyUsed.loadLibrary().then(onLoad);
onLoad(loadSucceeded) => loadSucceeded ? doStuff() : makeExcuses(); 对loadLibrary()的调用是异步的
loadLibrary()返回的future 代表一个表示加载是否成功的布尔量
doStuff() { rarelyUsed.respondToMenuRequest();}
相关语言
总结
|
函数
参数
位置参数
必填参数
zero() => 0; //没有参数的函数;从技术角度上讲,它有0 个参数
get zero => 0; //上面函数的另一版本
id(x) => x; // identity 函数
identity(x) {
return x;
} //一个更烦琐的过entity 函数
add(a, b) => a + b; //有两个必填参数的函数 可选参数
increment(x, [step = 1]) => x + step; // step 是可选的,默认值是1
main() {
increment(1); //值为2
increment(2, 4); //值为6
increment(); //运行时错误
increment(2, 3, 4); //运行时错误
} 命名参数
一个完全依赖千命名参数的例子:
class Address {
var street, number, city, zip, country;
}
addressLetter({name: '', street: '', number, city, zip, country}) {
var addr = new Address();
addr.street = street;
addr.number = number;
addr.city = city;
addr.zip = zip;
addr.country = country;
return addr;
}
main() {
addressLetter(street: "Downing", number: 10);
addressLetter(street: "Wall", city: "New York", country: "USA");
addressLetter(city: "Paris", country: "France");
addressLetter(name: "Alice", country: "Wonderland");
addressLetter();
addressLetter(name: "room", number: 101, country: "Oceania");
} 必填参数与命名参数混合的情况:var map = new Map();
fail() => throw ('Key not found');
lookup(key, {ifMissing: fail}) {
var result = map[key];
if (result == null) {
return ifMissing();
}
return result;
}
lookup("anything"); //抛出错误
lookup("any七hing", ifMissing: () => map["anything"] = 42); //返回值为42
var map = new Map();
lookup(key, {ifMissing}) {
var result = map[key];
if (result != null) {
return result;
}
return ifMissing == null ? throw "$key notfound" : ifMissing();
} 命名参数始终是可选的
形式参数不是final 变量
函数体
构造函数
函数声明
局部函数
fib(n) {
lastTwo(n) {
if (n < 1) {
return [0, 1];
} else {
var p = lastTwo(n - 1);
return [p[1], p[0] + p[1]];
}
}
return lastTwo(n)[1];
}
闭包
(x) => x; //另一个identity 函数
(x) { return x;} //又一个
(x, [step = 1]) => x + step; //有一个可选参数的闭包
(a, b) => a + b; //有两个必填参数的闭包
reduce()
sum(nums) => nums.reduce((a, b) => a + b);
where()country.cities.where((city) =>city.population> 1000000);
调用方法与函数
print('Hello, oh brave new world that has such people in it' )
```。
>有些函数被称为getter, 可以不使用参数列表来调用。
```dart
true.runtimeType; // bool
级联
"Hello".length.toString(); // 值为'5'
"Hello"..length; //值为 Hello 对象
"Hello"..length.toString(); //值为“Hello"
var address= new Address.of("Freddy Krueger");
address.setStreet ("Elm", "13a");
address.city = "Carthage";
address.state = "Eurasia";
address.zipCode(66666, extend: 66666);
address;
new Address.of("Freddy Krueger")
..setStreet("Elm", "13a")
..city = "Carthage"
..state = "Eurasia"
..zipCode(66666, extend: 66666);
var sortedColors =
['red', 'green', 'blue', 'orange', 'pink'].sublist(1, 3).sort();
var colors = ['red', 'green', 'blue', 'orange', 'pink'].sublist(1, 3);
colors.sort();
var sortedColors = ['red', 'green', 'blue', 'orange', 'pink'].sublist(1, 3)
..sort(); 赋值
使用运算符
Function 类
static apply(Function function,List positionalArguments,[Map<Symbol, dynamic>namedArguments])
模拟函数
// 存疑
var p = new Proxy ((x) => x*2);
p (1); //我们希望得到2
函数作为对象
一个函数表达式每被计算一次,就可能分配一个新的函数对象。
makeCounter() {
var counter = 0;
increment() => ++counter;
return increment;
}
顶层或静态的函数声明可以被命名,且它们的名称始终表示同一个对象。
不同函数的运行时类型
相同的函数具有相同的运行时类型。生成器函数
迭代器与可迭代对象
class Naturalsiterable {
var n;
Naturalsiterable.to(this.n);
get iterator => new Naturallterator(n);
}
class Naturallterator {
var n;
var current = -1;
Naturallterator(this.n);
moveNext() {
if (current < n) {
current++;
return true;
}
return false;
}
}
naturalsTo(n) => new Naturalsiterable.to(n);
main() {
for (var i in naturalsTo(20)) {
print(i);
}
}
同步生成器
naturalsTo(n) sync* {
var k = 0;
while (k < n) yield k++;
}
naturalsTo (n) => new Iterable. generate (n, (x) => x);
生成器函数的函数体是在函数返回一个结果给调用者之后才开始执行的
相关语言
总结
|
类型
可选类型
Dart 坚持类型注解不影响语义这一原则
类型之旅
int sum(int a, int b) => a + b;
void main() {
print(sum(3, 4));
}
Object 类型
dynamic 类型
dynamic sum(dynamic a, dynamic b) => a + b; //永远不要这样做!
Pointimport 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
Point scale(num factor) => new Point(x * factor, y * factor);
Point operator +(Point p) => new Point(x + p.x, y + p.y);
static num distance(Point p1, Point p2) {
num dx = p1.x - p2.x;
num dy = p1.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
}
接口类型
implements
abstract class Pair {
get first;
get second;
}
class ArrayPair implements Pair {
var _rep;
ArrayPair(a, b) {
_rep = [a, b];
}
get first => _rep[0];
get second => _rep[1];
}
Pair reversePair(Pair p) => new ArrayPair(p.second, p.first);
reversePair(new ArrayPair(3, 4)); //一个新的Pair对象,first = 4 且second = 3
Dart 选择非严格的类型检查。
泛型
参数化类型
List<String> L = [];
Map<String, int> m = {}; 给泛型类提供类型参数并不是必需的
在某些情况下显式使用dynamic 类型是可取的 Map<String, dynamic> mm = {}; 函数类型类型具体化
类型检测
var v = [1, 2, 3];
v is List; // true
v is Map; // false
v is Object; //无意义的:始终为true
强制类型转换
Object o = [3, 4, 5];
o as List; //有点昂贵的空操作
o as Map; //抛出异常 强制类型转换大致上可以看作以下方式的简写: var t = e;
t is T ? t : throw new CastError(); 强制类型转换的典型用法是数据校验 List L = readNextVal() as List;
//我确信我从readNextVal( )中得到的是一个列表
//如果不是,事情搞砸了,那么我应该失败
//接下来,对列表进行处理 应该警惕对强制类型转换的滥用Object o = [5, 6, 7];
// 大量的中间逻辑
o.length;//正常工作,但会产生类型警告:因为不是所有对象都有length 属性
Object o = [5, 6, 7];
//相同的中间逻辑
(o as List).length; //糟糕!避免警告的错误方式
Object O = [5, 6, 7];
//相同的中间逻样
List L = O;
L.length; 检查模式
num n = 3.0;
int i = n; //梒查模式下将触发动态错误;,生产模式下正常工作
num x = i; //始终正常工作
int j = null;
具体化泛型
var L = new List<String>();
L is List<String>; // true
L is List<int>; // false
var L = new List<String>();
L[0] = 'abc'; //始终ok
L[1] = 42; //检查模式下无法运行- 42 是整型,不是String 的子类型
具体化和可选类型
typedef int IntFunction(int);
observeAnnotations(f) {
return f is IntFunction;
}
String idl(String x) => x;
id2(x) => x;
int id3(int x) => x;
main() {
observeAnnotations(idl); // false
observeAnnotations(id2); // true
observeAnnotations(id3); // true
}
类型和代理 |
表达式和语句 |
反射 |
异步和isolate |
结论 |
|
Dart 语言简介
移动端开发
Web 开发
服务端开发
|
Dart 语法基础关键字
|
Dart
Dart 开发语言概览
一个简单的 Dart 程序
重要概念
关键字
变量 Variables
变量仅存储对象的引用
默认值
final 和 const
使用关键字 const 修饰变量表示该变量为 编译时常量。
内置类型
num
int
整型字面量将会在必要的时候自动转换成浮点数字面量:
整型支持传统的位移操作
double
字符串和数字之间转换的方式:
数字字面量为编译时常量
字符串 String
${表达式}
多行字符串
“raw” 字符串
字符串字面量的插值表达式
bool
应该总是显示地检查布尔值
List
可以在 Dart 的集合类型的最后一个项目后添加逗号
List 的下标索引从 0 开始
在 List 字面量前添加 const 关键字会创建一个编译时常量:
扩展操作符
...
和 空感知扩展操作符...?
可以使用扩展操作符
...
将一个 List 中的所有元素插入到另一个 List 中:如果扩展操作符右边可能为 null ,你可以使用 null-aware 扩展操作符
...?
来避免产生异常:集合中的 if 和 集合中的 for 操作
使用 集合中的 if 来创建一个 List 的示例,它可能包含 3 个或 4 个元素:
使用 集合中的 for 将列表中的元素修改后添加到另一个列表中的示例:
Set
可以使用在
{}
前加上类型参数的方式创建一个空的 Set,或者将{}
赋值给一个 Set 类型的变量:使用
add()
方法或addAll()
方法向已存在的 Set 中添加项目:使用
.length
可以获取 Set 中元素的数量:可以在 Set 字面量前添加 const 关键字创建一个 Set 编译时常量:
从 Dart 2.3 开始,Set 可以像 List 一样支持使用扩展操作符
...
和...?
以及 Collection if 和 for 操作Map
可以使用 Map 的构造器创建 Map:
向现有的 Map 中添加键值对与 JavaScript 的操作类似:
如果检索的 Key 不存在于 Map 中则会返回一个 null:
使用 .length 可以获取 Map 中键值对的数量:
在一个 Map 字面量前添加 const 关键字可以创建一个 Map 编译时常量:
Map 可以像 List 一样支持使用扩展操作符
...
和...?
以及集合的 if 和 for 操作。runes 与 grapheme clusters
Symbol
在标识符前加
#
前缀来获取 Symbol函数 Function
参数 Parameter
命名参数
可选的位置参数
默认参数值
设置可选参数默认值示例:
为位置参数设置默认值:
List 或 Map 同样也可以作为默认值
main()
函数下面是一个简单 main() 函数:
使用命令行访问带参数的
main()
函数示例:函数是一级对象
可以将函数作为参数传递给另一个函数
可以将函数赋值给一个变量
匿名函数
如果函数体内只有一行返回语句,你可以使用胖箭头缩写法。
词法作用域
词法闭包
测试函数是否相等
返回值
运算符 Operator
算术运算符
– | 减
-表达式 | 一元负, 也可以作为反转(反转表达式的符号)
/ | 除
~/ | 除并取整
% | 取模
关系运算符
==
运算符的一些规则:类型判断运算符
赋值运算符
逻辑运算符
按位和移位运算符
条件表达式
级联运算符
如果级联操作的对象可以为空,则在第一次操作中使用空级联
?..
。从?..
开始保证该空对象上不尝试任何级联操作。级联运算符可以嵌套
在返回对象的函数中谨慎使用级联操作符。
其他运算符
流程控制语句
If 和 Else
For 循环
在 Dart 语言中,for 循环中的闭包会自动捕获循环的 索引值 以避免 JavaScript 中一些常见的陷阱。
如果要遍历的对象是一个可迭代对象(例如 List 或 Set),并且你不需要知道当前的遍历索引,则可以使用 for-in 方法进行 遍历:
While 和 Do-While
while 循环会在执行循环体前先判断条件:
do-while
循环则会 先执行一遍循环体 再判断条件:Break 和 Continue
Switch 和 Case
不匹配任何 case 语句的情况下,会执行 default 子句中的代码:
忽略了 case 子句的 break 语句,会产生错误:
但是,Dart 支持空的 case 语句,允许其以
fall-through
的形式执行。在非空 case 语句中想要实现
fall-through
的形式,可以使用 continue 语句配合 label 的方式实现:断言 assert
assert 的第二个参数可以为其添加一个字符串消息。
异常 Exception
抛出异常
捕获异常
Finally
类 class
使用类的成员
使用构造函数 constructor
获取对象的类型
实例变量
构造函数
默认构造函数
构造函数不被继承
命名式构造函数
可以为一个类声明多个命名式构造函数来表达更明确的意图:
调用父类非默认构造函数
初始化列表
重定向构造函数
常量构造函数
工厂构造函数
方法
实例方法
操作符
为了表示重写操作符,使用 operator 标识来进行标记。
Getter 和 Setter
抽象方法
抽象类 abstract
抽象类常常会包含 抽象方法。
隐式接口 implements
扩展一个类 extends
重写类成员 @OverRide
covariant
如果重写 == 操作符,必须同时重写对象 hashCode 的 Getter 方法。
noSuchMethod 方法
只有下面其中一个条件成立时,你才能调用一个未实现的方法:
扩展方法
枚举类型
使用枚举 enum
使用 mixin 为类添加功能
使用 with 关键字并在其后跟上 mixin 类的名字来使用 mixin 模式:
实现一个 mixin
可以使用关键字 on 来指定哪些类可以使用该 Mixin 类,
类变量和方法 static
静态变量
静态方法
泛型 Generic
为什么使用泛型?
使用集合字面量
使用类型参数化的构造函数
泛型集合以及它们所包含的类型
限制参数化类型
<T extends SomeBaseClass>
使用泛型方法
function<T>
库和可见性
使用库 import
指定库前缀 as
导入库的一部分 show hide
延迟加载库 deferred as
实现库
异步支持
处理 Future
声明异步函数 async
处理 Stream
使用 await for 定义异步循环看起来是这样的:
使用 break 和 return 语句可以停止接收 Stream 数据,这样就跳出了循环并取消注册监听 Stream。
如果在实现异步 for 循环时遇到编译时错误,请检查确保 await for 处于异步函数中。
生成器 generator
可调用类 call
隔离区
类型别名 typedef
元数据
自定义元数据注解
注释
单行注释
多行注释
文档注释
Dart 编程语言规范
The text was updated successfully, but these errors were encountered: