woof英语怎么读语音,woof英语的读法

  

  本文是Flutter学习指南的第四篇,假设读者有一些编程经验。通过快速浏览Dart的一些基本特性,读者可以具备使用它进行开发的基本能力。   

  

  

变量

  

  

  基本类型   

  

  bool done=trueint num=2;双x=3.14final bool visible=false最终int金额=100;最终双y=2.7const bool debug=trueconst int sum=42const double z=1.2复制代码不同于其他常用语言。Dart没有字节,char和float,int和double都是64位。和final Java中的final一样,表示一个运行时常量(在程序运行时赋值,赋值后值不会改变)。Const表示编译时常数,其值在程序编译时确定。   

  

  如果觉得每次都写变量类型太麻烦,应该喜欢Dart的类型推断功能:   

  

  var done=truevar num=2;var x=3.14final visible=false最终金额=100;最终y=2.7const debug=trueconst sum=42const z=1.2复制代码Dart中的一切都是对象,包括int和function。   

  

  String   

  

  var str=' foovar str 2=str . toupper case();var str 3=str . trim();assert(str==str 2);断言(!相同(str,str 2));复制代码Dart中的字符串与Java中的不可变对象相同;不同的是,要检测两个字符串的内容是否是同一件事,我们用==进行比较;如果要测试两个对象是否是同一对象(同一性测试),请使用indentity函数。   

  

  List、Map 和 Set   

  

  List   

  

  //使用构造函数//Follow var list=new Listint()创建对象;same var list=Listint();list . add(1);list . add(2);//按字面量创建对象,list的泛型参数可以从变量定义中推断出来。//建议使用literal方法创建对象var list2=1,2;//没有元素,泛型参数显式指定为intvar list3=intlist 3 . add(1);list 3 . add(2);var list4=const1,2;//list4指向一个常量,我们不能给它添加元素(不能修改)。list 4 . add(3);//错误//list4本身不是常量,所以可以指向另一个对象list4=4,5;//是fineconst list5=1,2;//相当于const list5=const1,2;list 5 . add(3);//错误//Dart还提供了for-in循环。//因为设计语音的时候就考虑到了这个需求,所以in是Dart var list6=1,3,5,7中的一个关键字;for(列表6中的变量e){ print(e);}复制Dart 2中的代码。创建对象时可以省略new关键字,也建议省略new。   

  

  Set   

  

  var set=SetString();set . add(' foo ');set . add(' bar ');assert(set . contains(' foo '));复制代码。我们只能通过Set的构造函数来创建实例。   

  

  Map   

  

  var map=MapString,int();//添加map ' foo '=1;map ' bar '=3;//修改map ' foo '=4;//对应的键不存在时,返回NULLIF(map ' foobar '==null){ print(' map不包含foobar ');}var map2=const { 'foo': 2,' bar': 4,};var map3=String,String { };复制代码dynamic 和 Object   

  

  我们前面说过,Dart中的一切都是对象。所有这些对象的父类都是Object。   

  

  Object o=' stringo=42o . tostring();//我们只能调用Object支持的dynami方法   

c obj = 'string';obj<'foo'> = 4; // 可以编译通过,但在运行时会抛出 NoSuchMethodError复制代码Object 和 dynamic 都使得我们可以接收任意类型的参数,但两者的区别非常的大。

  

使用 Object 时,我们只是在说接受任意类型,我们需要的是一个 Object。类型系统会保证其类型安全。

  

使用 dynamic 则是告诉编译器,我们知道自己在做什么,不用做类型检测。当我们调用一个不存在的方法时,会执行 noSuchMethod() 方法,默认情况下(在 Object 里实现)它会抛出 NoSuchMethodError。

  

为了在运行时检测进行类型检测,Dart 提供了一个关键字 is:

  

dynamic obj = <String, int>{};if (obj is Map<String, int>) { // 进过类型判断后,Dart 知道 obj 是一个 Map<String, int>, // 所以这里不用强制转换 obj 的类型,即使我们声明 obj 为 Object。 obj<'foo'> = 42;}// 虽然 Dart 也提供了 as 让我们进行类型的强制转换,但为了进来更安全// 的转换,更推荐使用 isvar map = obj as Map<String, int>;复制代码

语句

var success = true;if (success) { print('done');} else { print('fail');}for (var i = 0; i < 5; ++i) { print(i);}var sum = 0;var j = 1;do { sum += j; ++j;} while (j < 5);while (sum-- > 0) { print(sum);}var type = 1;switch (type) { case 0: // ... break; case 1: // .. break; case 2: // ... break; default: // ... break;}复制代码常见的 if/else,do while,while 和 switch 在 Dart 里面都支持。switch 也支持 String 和 enum。

  

函数

最普通的函数看起来跟 Java 里的一样:

  

int foo(int x) { return 0;}复制代码Dart 也支持可选参数:

  

void main() { print(foo(2)); print(foo(1, 2));}int foo(int x, ) { // 是的,int 也可以是 null if (y != null) { return x + y; } return x;}// 结果:// 2// 3复制代码默认参数也是支持的:

  

int foo(int x, ) { return x + y;}复制代码还能用具名参数(named parameters):

  

void main() { print(foo(x: 1, y: 2)); // 具名参数的顺序可以是任意的 print(foo(y: 3, x: 4)); // 所有的具名参数都是可选的,这个调用是合法的,但它会导致 foo() 在运行时抛异常 print(foo());}int foo({int x, int y}) { return x + y;}复制代码具名参数也可以有默认参数:

  

void main() { print(foo(x: 1, y: 2)); print(foo());}int foo({int x = 0, int y = 0}) { return x + y;}复制代码如果想告诉用户某个具名参数是必须的,可以使用注解 @required:

  

int foo({@required int x, @required int y}) { return x + y;}复制代码@required 是 meta 包里提供的 API,更多的信息读者可以查看 pub.dartlang.org/packages/me…。

  

函数还可以在函数的内部定义:

  

// typedef 在 Dart 里面用于定义函数类型的别名typedef Adder = int Function(int, int);Adder makeAdder(int extra) { int adder(int x, int y) { return x + y + extra; } return adder;}void main() { var adder = makeAdder(2); print(adder(1, 2));}// 结果:// 5复制代码像上面这样简单的函数,我们还可以使用 lambda:

  

typedef Adder = int Function(int, int);Adder makeAdder(int extra) { return (int x, int y) { return x + y + extra; }; // 如果只有一个语句,我们可以使用下面这种更为简洁的形式 // return (int x, int y) => x + y + extra;}void main() { var adder = makeAdder(2); print(adder(1, 2));}复制代码Dart 里面不仅变量支持类型推断,lambda 的参数也支持自动推断。上面的代码还可以进一步简化为:

  

typedef Adder = int Function(int, int);Adder makeAdder(int extra) { // 我们要返回的类型是 Adder,所以 Dart 知道 x, y 都是 int return (x, y) => x + y + extra;}void main() { var adder = makeAdder(2); print(adder(1, 2));}复制代码美中不足的是,Dart 不支持函数的重载。

  

异常

抛出异常:

  

throw Exception('put your error message here');复制代码捕获异常:

  

try { // ...// 捕获特定类型的异常} on FormatException catch (e) { // ...// 捕获特定类型的异常,但不需要这个对象} on Exception { // ..// 捕获所有异常} catch (e) { // ...} finally { // ...}复制代码跟 Java 不同的是,Dart 可以抛出任意类型的对象:

  

throw 42;复制代码

定义一个类:

  

class Point2D { static const someConst = 2; int x; // 成员变量也可以是 final 的 final int y; Point2D(int x, int y) { this.x = x; this.y = y; }}复制代码由于这种初始化方式很常见,Dart 提供了更简洁的方式:

  

class point2d { int x; int y; point2d(this.x, this.y);}复制代码此外,还可以使用初始化列表(initializer list)对对象进行初始化:

  

class Point2D { int x; int y; // 由于是在 initializer list 中,Dart 知道第一个 x 是 this.x, // 第二个 x 是构造函数的参数 Point2D(int x, int y) : x = x, y = y { // ... }}复制代码initializer list 会在构造函数的函数体运行前执行。

  

Dart 具有垃圾收集功能,对象的使用跟 Java 里几乎是一样的:

  

main() { var point = Point2D(1, 2); point.x = 4; print(point);}class Point2D { int x; int y; Point2D(this.x, this.y); // 所有的类都继承自 Object,toString() 是 Object 中的方法 @override String toString() { // 在字符串的内部可以通过 ${expression} 的方式插入值,如果 // expression 是一个变量,可以省略花括号 return "Point2D{x=$x, y=$y}"; }}// 结果:// Point2D{x=4, y=2}复制代码Dart 使用 package 的概念来管理源码和可见性。它没有 public、private 之类的访问权限控制符,默认情况下,所有的符号都是公开的。如果我们不想某个变量对包的外部可见,可以使用下划线开头来给变量命名。

  

class _Foo { // ...}class Bar { int _x;}复制代码下面我们使用 Dart 的访问控制,实现一个带偏移量的 Point:

  

class OffsetPoint { int _x; int _y; int offset; OffsetPoint(int x, int y, int offset) : _x = x, _y = y, offset = offset {} // 定义一个 getter int get x => _x + offset; // getter 不能有参数,连括号都省掉了 int get y { return _y + offset; } // 定义 setter void set x (int x) => _x = x; void set y (int y) => _y = y; @override String toString() { return "OffsetPoint{x=$x, y=$y}"; }}main() { var point = OffsetPoint(1, 2, 10); // 使用 getter/setter 时,就像它是一个普通的成员变量 print(point.x) print(point); point.x = 4; print(point);}// 结果:// 11// OffsetPoint{x=11, y=12}// OffsetPoint{x=14, y=12}复制代码在 Dart 里继承对象也很简单:

  

class Point2D { int x; int y; Point2D(this.x, this.y);}class Point3D extends Point2D { int z; // 父类的构造函数只能在 initializer list 里调用 Point3D(int x, int y, int z): z = z, super(x, y) { }}复制代码但是对象构造时它跟 Java、C++ 都不太一样:

  

先执行子类 initializer list,但只初始化自己的成员变量初始化父类的成员变量执行父类构造函数的函数体执行之类构造函数的函数体基于这个初始化顺序,推荐是把 super() 放在 initializer list 的最后。此外,在 initializer list 里不能访问 this(也就是说,只能调用静态方法)。

  

虽然 Dart 是单继承的,但它也提供了一定程度的多重继承支持:

  

abstract class Bark { void bark() { print('woof'); }}class Point3D extends Point2D with Bark { int z; // 父类的构造函数只能在 initializer list 里调用 Point3D(int x, int y, int z): z = z, super(x, y) { }}// 没有其他类需要继承,所以直接 extends Bark 就可以了class Foo extends Bark {}void main() { var p = Point3D(1, 2, 3); p.bark();}复制代码Dart 把支持多重继承的类叫做 mixin。更详细的介绍,读者可以参考www.dartlang.org/articles/la…。

  

泛型

class Pair<S, T> { S first; T second; Pair(this.first, this.second);}void main() { var p = Pair('hello', 2); print(p is Pair<String, int>); // is! 也是 Dart 的运算符,下面的语句跟 !(p is Pair<int, int>) 是一样的, // 但 is! 读起来跟像英语 print(p is! Pair<int, int>); print(p is Pair);}// 结果:// true// true// true复制代码跟 Java 不同,Dart 的泛型参数类型在运行时是保留的。

  

Future

Dart 是单线程的,主线程由一个事件循环来执行(类似 Android 的主线程)。对于异步代码,我们通过 Future 来获取结果:

  

import 'dart:io';void foo() { var file = File('path-to-your-file'); file.exists() .then((exists) => print('file ${exists ? 'exists' : 'not exists'}')) .catchError((e) => print(e));}复制代码Dart 2 提供了 async 函数,用来简化这种编程范式。下面这段代码的效果跟上面是一样的:

  

void foo() async { var file = File('path-to-your-file'); try { var exists = await file.exists(); print('file ${exists ? 'exists' : 'not exists'}'); } catch (e) { print(e); }}复制代码但是要注意,上面两段代码并不是完全一样的:

  

// import 语句用于导入一个包import 'dart:io';void main() { foo(); bar();}void bar() { var file = File('path-to-your-file'); file.exists() .then((exists) => print('bar: file ${exists ? 'exists' : 'not exists'}')) .catchError((e) => print(e)); print('bar: after file.exists() returned');}void foo() async { var file = File('path-to-your-file'); try { var exists = await file.exists(); print('bar: file ${exists ? 'exists' : 'not exists'}'); print('bar: after file.exists() returned'); } catch (e) { print(e); }}// 一种可能的结果:// bar: after file.exists() returned// foo: file not exists// foo: after file.exists() returned// bar: file not exists

相关文章