void main(){
print('Hello Word');
}
如果未初始化的变量,其默认值为null
//常量
const a = 10;
//变量
var b = 10;
Dart没有public、protected、和private关键字,标识符(_)表示私有的意思
//默认为public
int a = 10;
//下划线开头为private
int _a = 10;
final和const都表示常量的意思,其值都不可修改,两者最大的区别
final a = 10;
const b = 10;
class Main(){
final a = 10;
//如果const变量在类中,需要加上static
//因为类未初始化,该值无法被视为编译时变量,否则会报错
static const b = 10;
}
dart语法的const相当于java这种写法
private static final int a = 10;
若干个表达式引用为编译时常量,其结果也是编译时常量
const a = "Hello";
const b = "Word";
const c = "$a $b";
1、基本类型
Dart内置的可用类型
2、number
/
和~/
的区别
int a = 10;
int b = 2;
print(a/b); //5.0
print(a~/b); //5
??
和??=
的区别
//??属于条件表达式,如果b是null,则执行toString()并返回其结果,如果不是null,则返回其值
b ?? b.toString();
//??=属于赋值表达式,如果b是null,则赋值给b,如果不是null,则b的值保持不变
b ??= value;
?.
和??
的配合使用
//padding为空,则返回1,padding不为空,则返回padding.value
int a = padding?.value ?? 1
3、boolean
true和false所创建的对象都是编译时常量。当Dart需要一个布尔值的时候,只有true对象才被认为是true,所有其他的值都是flase
4、string
String str1 = 'HelloWord'; //普通字符串
String str2 = """; //段落
go
""";
String str3 = r'Hello /n Word'; //不转义
print(str3 * 5); //重复5次
print(str3 == str4); //相等
print(str3[0]); //获取字符
print('a + b = ${a + b}') //插值表达式
5、list
var list = [1,2,3];
var list = const [1,2,3]; //定义不可变列表
var list = new List();
var list = new List.generate(1000, (i)=>"Item $i");
6、map
var map = {'1':'c','2':'java'};
var map = const{'1':'c','2':'java'}; //定义不可变映射
var map = new Map();
7、dynamic
dynamic a = 10; //任意类型变量
var list = new List(); //任意类型列表
8、runes
runes代表字符串的Unicode编码
Runes input = new Runes('\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input)); //输出一排表情
9、enum
enum Color {red,green,blue} //枚举的定义
assert(Color.red.index == 0); //枚举索引获取
List colors = Color.values; //枚举列表获取
operator关键字可以复写操作符
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);
}
}
1、函数的返回类型和参数类型都是可以省略的
getPerson(name,age){
return new Person(name,age);
}
2、函数的实现体可以通过符号进行表示
getPerson(name,age) => new Person(name,age);
3、可选参数(重载函数)
花括号参数表示可选命名参数
getPerson(name,{age,weight}) => new Person(name,age,weight);
getPerson("张三",weight:55);
方括号参数表示可选位置参数,不需要别名,但是位置必须是固定的参数
getPerson(name,[age,weight]) => new Person(name,age,weight);
getPerson("张三",18,55);
4、默认参数
getPerson(name,age=18) => new Person(name,age);
5、构造函数
@required
表示必须传参
class Person{
var name;
var age;
//这里默认等同于this.name=name,this.age=age
Person({@required this.name,this.age});
}
当前为StatelessWidget组件中的构造方法
class MyApp extends StatelessWidget{
final List items;
MyApp({Key key,@required this.items}):super(Key:key);
}
常量构造函数
class Point {
const Point(this.x, this.y);
}
命名构造函数
class Point {
num x;
num y;
Point(this.x, this.y);
//可以直接命名的构造函数,命名构造函数也是可以直接实例化的
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}
默认情况下,子类的构造函数会自动调用超类的无名无参数的默认构造函数,如果超类没有无名无参数构造函数,则你需要手工的调用超类的其他构造函数,在构造函数参数后使用冒号可以调用超类构造函数。如果提供了一个initializer list
(初始化参数列表),则初始化参数列表在超类构造函数执行之前执行。下面是构造函数执行顺序:
class Point {
num x;
num y;
Point(this.x, this.y);
//初始化参数列表用冒号展开
//初始化表达式等号右边的部分不能访问this
Point.fromJson(Map jsonMap)
: x = jsonMap['x'],
y = jsonMap['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}
重定向构造函数
class Point {
num x;
num y;
Point(this.x, this.y);
//类似于重载
Point.alongXAxis(num x) : this(x, 0);
}
工厂方法构造函数
class Logger {
static final Map _cache = {};
//使用factory关键字表示工厂方法,其实现类似于单例模式的实现
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
}
6、get和set
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
7、函数参数
函数可以作为参数
final values = [1, 2, 3, 5, 10, 50];
//map和forEach参数里面可以传递函数
values.skip(1).take(3).map(func).forEach(print);
例如:forEach的源码实现
void forEach(void f(E element)) {
for (E element in this) f(element);
}
8、匿名方法
var fun = (){
print("Hello Word");
}
9、闭包
闭包最大的作用是可以访问方法体中的成员变量
count(){
int count = 0;
return (){
print(count++);
};
}
void main(){
var fun = count();
fun(); //1
fun(); //2
fun(); //3
}
10、返回值
所有的函数都返回一个值,如果没有指定返回值,则默认把语句return null;
作为函数的最后一个语句执行
11、静态函数
静态函数不再类实例上执行,所以无法访问this
异常的捕获可以用on
关键字进行捕获对应的异常,或者用rethrow
关键字进行重新抛出异常
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 指定捕获OutOfLlamasException
buyMoreLlamas();
} on Exception catch (e) {
// 指定捕获Exception类型的异常
print('Unknown exception: $e');
} catch (e) {
// 任意异常
print('Something really unknown: $e');
rethrow; // 重新抛出该异常
}
1、指定别名
当有类名冲突的时候,可以用不同的别名进行区分
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
Element element1 = new Element(); //使用lib1的Element类
lib2.Element element2 = new lib2.Element(); //使用lib2的Element类
2、导入指定功能
如果你只使用库的一部分功能,则可以选择需要导入的内容
import 'package:lib1/lib1.dart' show foo; //只导入foo库
import 'package:lib2/lib2.dart' hide foo; //导入除foo库的所有其他库
3、延迟导入
下面是一些使用延迟加载库的场景
import 'package:deferred/hello.dart' deferred as hello;
当需要使用的时候,使用库标识符调用 loadLibrary()函数来加载库,使用 await 关键字暂停代码执行一直到库加载完成
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
对象的方法和成员变量都可以进行级联调用,类似于Java的链式调用
//案例一
void main(){
num x = 10;
num y = 42; // not used
var p = new Point();
p..log('start')
..x = x
..scale(10)
..log('scaled')
..x = x + 1
..y = x + p.x + p.y;
print('p.x = ${p.x}, p.y = ${p.y}. x = $x');
}
//案例二
front
..beginPath()
..fillStyle = penColor
..arc(tx, ty, penWidth/2+2, 0, PI2, true)
..fill()
..moveTo(wx, wy)
..strokeStyle = "black"
..lineTo(tx, ty)
..closePath()
..stroke();
//案例三
querySelector('#button') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
//案例四
//级联调用也可以嵌套
final addressBook = (new AddressBookBuilder()
..name = 'jenny'
..email = '[email protected]'
..phone = (new PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
1、声明异步方法
一个异步方法是函数体被标记为async
的方法
checkVersion() async {
// ...
}
使用async
和await
的代码是异步的,要使用await
,其方法必须带有async
关键字
checkVersion() async {
var version = await lookUpVersion();
}
可以使用try-catch,和finally来处理使用await
的异常
try {
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4044);
} catch (e) {
}
异步方法返回值为Future
类型
String lookUpVersionSync() => '1.0.0';
Future lookUpVersion() async => '1.0.0';
在循环中使用异步
await for (var request in requestServer) {
handleRequest(request);
}
可调用类
//可以把类当做方法使用
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out'); //Hi there, gang!
}
typedef能对方法进行重命名,且只能使用在function类型,在构造函数中也可以传递方法
typedef int Compare(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
int sort(Object a, Object b) => 0;
main() {
SortedCollection coll = new SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
1、系统自带注解
@deprecated、 @override、@proxy
2、自定义注解
library todo;
class todo {
final String who;
final String what;
const todo(this.who, this.what);
}
import 'todo.dart';
@todo('xuyingjun', 'make this do something')
void doSomething() {
print('do something');
}