Dart的官网地址:https://www.dartlang.org/guides/language/language-tour#libraries-and-visibility
在Dart中有一个基本的概念需要先了解:
- 在 dart 中,所有的东西都是对象,无论是变量,数字或函数,所有的对象都是类的实例(包括null),所有的对象都从 Object 类继承
- 尽管Dart是强类型的,但类型注释是可选的,因为Dart可以推断类型。在上面的代码中,
number
推断为类型int
。如果要明确说明不需要任何类型,请 使用特殊类型dynamic
。 - Dart支持泛型类型,如
List<int>
(整数列表)或List<dynamic>
(任何类型的对象列表)。 - Dart支持顶级函数(例如
main()
),以及绑定到类或对象的函数(分别是静态方法(static方法)和实例方法(new对象后))。您还可以在函数内创建函数(嵌套函数或本地函数)。 - 类似地,Dart支持顶级变量,以及绑定到类或对象的变量(静态和实例变量)。实例变量有时称为字段或属性。(全局变量和局部变量类似的概念)
- 不具备关键字
public
,protected
和private
。如果标识符以下划线(_)开头,则它对其库是私有的
dynamic说明:
dynamic可以在两种情况下使用,
一种是:Dart的类型系统不够复杂,无法表示允许的类型集,或者值来自互操作或静态类型系统范围之外
一种是:希望运行时动态确认数据类型
void main(){
// a 的数据类型可以随意改变,这种类型就是 dynamic
var a ;
a = 10;
a = "dart";
// 这里我们使用 dynamic 声明
dynamic d = 10;
d = 'dart';
}
嵌套函数例子:
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
在线运行dart:
变量定义的关键字:
- var:变量
- dynamic:不指定类型
- final:声明一个只能赋值一次的变量
- const:常量,如果在类的级别进行生命,即作为整个类的变量的时候,需要使用static来修饰
支持的数据类型:
- numbers
- strings
- booleans
- lists (also known as arrays)
- maps
- runes (用于表示字符串中的Unicode字符)
- symbols
numbers
var x = 1;
var y = 1.1;
int z = 1;
strings
String str = "sss";
String str2 = 'sssd';
var s = "1234";
assert('Dart has $s, which is very handy.' ==
'Dart has string interpolation, ' +
'which is very handy.');
//这里的$s表示使用上面的s的值
//assert表示判断括号内的结果是否为true,否则抛出一个错误
booleans
bool result = false;
lists
var list = [1, 2, 3];
maps
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
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()的新建,从Dart2开始,new为可选字段
runes
在Dart中,runes是字符串的UTF-32代码
Unicode为世界上所有系统中使用的字母,使用数字和符号定义唯一的数值。
由于Dart字符串是一系列UTF-16代码单元,因此在字符串中表示32位Unicode值需要特殊语法
表达Unicode代码点的常用方法是 \uXXXX,其中XXXX是4位十六进制值。例如,(♥)是\u2665。要指定多于或少于4个十六进制数字,请将值放在大括号中
例如,笑表情符号(?)是\u{1f600}
例子:
main() {
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
}
结果:
?
[55357, 56399]
[128079]
♥ ? ? ? ? ?
symbols
老实说这块我不是很理解,写了个demo,感觉就像官网说的,以后可能永远都用不到
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
String str = "sss";
String str2 = 'sssd';
assert(new Symbol("sss") == #sss);
return new MaterialApp(
title: 'Welcome to Flutter',
home: new Scaffold(
// appBar: new AppBar(
// title: new Text('Welcome to Flutter'),
// ),
body: new Center(
child: new RandomWords(),
),
),
);
}
}
它正常运行下去了,仅此而已
方法Function:
常规方法
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
Dart建议设置返回类型(void,其他),但如果省略类型,该函数仍然有效:
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
对于只包含一个表达式的函数,可以使用简写语法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
方法传参说明:
参数必传:
bool isNoble(int atomicNumber){...}
参数选传:
void enableFlags({bool bold, bool hidden}) {...}
enableFlags(bold:false) //这样也可以调用
必传选传混杂:
String say(String from, String msg, [String device])
from,msg必传,device选传
void enableFlags({bool bold,@reqiured bool hidden}) {...}
此时hidden必传
选传参数默认值:
void enableFlags({bool bold = false, bool hidden = false}) {...}
String say(String from, String msg,
[String device = 'carrier pigeon', String mood]){...}
void doStuff(
{List<int> list = const [1, 2, 3],
Map<String, String> gifts = const {
'first': 'paper',
'second': 'cotton',
'third': 'leather'
}}){...}
传入方法:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
方法比较:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
匿名函数:
void main() {
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
}
结果:
0: apples
1: bananas
2: oranges
类型操作符:
Operator | Meaning |
---|---|
as | Typecast (also used to specify library prefixes) |
is | True if the object has the specified type |
is! | False if the object has the specified type |
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
值得备注的操作符:
// 赋值
a = value;
// 如果b为null则赋值,否则保持原样
b ??= value;
条件判断语句:
我这里就只列需要关注的东西了
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());
switch与java有些不同
//不局限于int类型的值
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(断言)
结果为true则继续执行,为false则包错
// Make sure the variable has a non-null value.
assert(text != null);
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
错误处理:
Throw抛出异常
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
Catch捕获异常
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
Class类说明:
//正常的类创建,类的属性默认有getter和setter方法(非final属性),
class Point {
num x;
num y;
//构造器语法糖
Point(this.x, this.y);
//新概念:命名构造器,在这个类会被继承,又本身需要构造器时,只能使用这种
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}
//如果是用继承,则不能用常规构造器,只能使用命名构造器
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// 命名构造器使用父类的,就使用符号:
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
//命名构造器的使用方式
var emp = new Employee.fromJson({});
简写方式:
class Employee extends Person {
// ...
Employee() : super.fromJson(findDefaultData());
}
Overridable operators(可覆写的操作符)
class Vector {
final int x;
final int y;
const Vector(this.x, this.y);
/// Overrides + (a + b). 可以将两个对象直接相加后产生新对象
Vector operator +(Vector v) {
return new Vector(x + v.x, y + v.y);
}
/// Overrides - (a - b). 可以将两个对象直接相减后产生新对象
Vector operator -(Vector v) {
return new Vector(x - v.x, y - v.y);
}
}
main() {
final v = new Vector(2, 3);
final w = new Vector(2, 2);
// v == (2, 3)
assert(v.x == 2 && v.y == 3);
// v + w == (4, 5)
assert((v + w).x == 4 && (v + w).y == 5);
// v - w == (0, 1)
assert((v - w).x == 0 && (v - w).y == 1);
}
interfaces(隐式接口)
这里的interface接口和java不同在于,不需要定义interface,任何class都可以被implements
这里的interface接口和java不同在于,不需要定义interface,任何class都可以被implements
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Imposter implements Person {
// We have to define this, but we don't use it.
final _name = "";
String greet(who) => 'Hi $who. Do you know who I am?';
}
greetBob(Person person) => person.greet('bob');
main() {
print(greetBob(new Person('kathy')));
print(greetBob(new Imposter()));
}
Adding features to a class: mixins(为类添加新的功能)---类似于多继承
这是一个很值得注意的特性,这个特性很容易实现类似于多继承的实现
abstract class Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
class Person{
final name = "name";
}
class Musician extends Person with Musical {
// ...
void doSome(){
entertainMe();
print(name);
}
}
void main(){
var mu = Musician();
mu.canPlayPiano = true;
mu.doSome();
}
泛型的使用:
与java中完全一致
Library库的说明:
库分两种类型
import 'dart:io';//对于内置的库,URI 使用特殊的 dart: scheme
import 'package:mylib/mylib.dart';//对于其他的库,你可以 package: scheme
import 'pk/met.dart';//对于其他的库,也可以直接使用路径
导入一部分库
// 只导入foo.
import 'package:lib1/lib1.dart' show foo;
// 除了foo都导入.
import 'package:lib2/lib2.dart' hide foo;
延迟加载入库
import 'package:deferred/hello.dart' deferred as hello;
greet() async {
await hello.loadLibrary();// 使用 await 关键字暂停代码执行一直到库加载完成
hello.printGreeting();
}
Asynchrony support(异步支持)
最常见的特性是 async
方法和 await
表达式。
async可以单独使用:
在一个方法上添加 async
关键字,则这个方法返回值为 Future。 例如,下面是一个返回字符串 的同步方法:
Future<String> lookUpVersion() async => '1.0.0';
如果使用 async 关键字,则该方法 返回一个 Future,并且 认为该函数是一个耗时的操作。
Future<String> lookUpVersion() async => '1.0.0';
例子:
//使用async之后方法的返回值为Future
getAppName() async{
return "1111";
}
void main(){
Future future = getAppName();
future.then((onValue){//在then中获取实际返回的值
return getAppName();//这里再返回一个Future
}).then((onValue){//上面返回的还是Future,则再一次then来获取另一个Future中的值
print(onValue);
});
}
await必须和async一起使用:
//看起来就像同步代码一样
runUsingAsyncAwait() async {
//...
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
}
//异步的错误捕捉
attached() async {
super.attached();
try {
await appObject.start();
} catch (e) {
//...handle the error...
}
}
异步的一些常用用法示例:
//串联异步请求
Future result = costlyQuery();
return result.then((value) => expensiveWork())
.then((value) => lengthyComputation())
.then((value) => print('done!'))
.catchError((exception) => print('DOH!'));
//异步请求合并
Future deleteDone = deleteLotsOfFiles();
Future copyDone = copyLotsOfFiles();
Future checksumDone = checksumLotsOfOtherFiles();
Future.wait([deleteDone, copyDone, checksumDone])
.then((List values) {
print('Done with all the long steps');
});