import
关键字导入dart:xxxx
package:xxxx
如果两个库代码有冲突,可以指定库前缀
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// 使用 lib1 的 Element 类。
Element element1 = Element();
// 使用 lib2 的 Element 类。
lib2.Element element2 = lib2.Element();
只想使用代码库中的一部分,你可以有选择地导入代码库
// 只导入 lib1 中的 foo。(Import only foo).
import 'package:lib1/lib1.dart' show foo;
// 导入 lib2 中除了 foo 外的所有。
import 'package:lib2/lib2.dart' hide foo;
单行注释以 //
开始。所有在 //
和该行结尾之间的内容被编译器忽略。
// 单行注释
/` 开始,以 `/
结尾。所有在 /` 和 `/
之间的内容被编译器忽略void main() {
/*
* This is a lot of work. Consider raising chickens.
Llama larry = Llama();
larry.feed();
larry.exercise();
larry.clean();
*/
}
/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
String name;
/// Feeds your llama [Food].
///
/// The typical llama eats one bale of hay per week.
void feed(Food food) {
// ...
}
/// Exercises your llama with an [activity] for
/// [timeLimit] minutes.
void exercise(Activity activity, int timeLimit) {
// ...
}
}
在生成的文档中,[Food] 会成为一个链接,指向 Food 类的 API 文档。
也就是说,在生成的文档中[Food]这个标识符就可以显示一个链接。
// 自定义一个类型
typedef Compare = int Function(Object a, Object b);
/// 使用类型定义的情况
class SortedCollection {
Compare compare; // 自定义类型
SortedCollection(this.compare);
}
// 简单的不完整实现。
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
print(coll.compare is Function); // true
print(coll.compare is Compare); // true
}
(?.)
避免表达式为nullvoid main(List<String> args) {
Person p = Person();
p.name = 'tom';
p.age = 12;
print(p.name); // tom
/// ?.
// 因为p2是null,所以无法设置并且打印
// 但是使用了?.以后就不会报错了。
Person p2;
p2?.name = 'jack';
p2?.age = 13;
print(p2?.name); // null
}
class Person{
String name;
int age;
}
void main(List<String> args) {
// 通过 类 创建实例
Person p = Person('tom', 12);
print(p.name); // tom
print(p.age); // 12
// 通过 类名.标识符 创建实例
Person p2 = Person.fromJson({'name': 'jack', 'age': 13}) ;
print(p2.name); // jack
print(p2.age); // 13
Animal a = const Animal('titi', 2);
Animal b = const Animal('titi', 2);
print(a.name);
print(a.age);
print(b.name);
// 两个实例相等
print(identical(a,b)); // true
}
class Person{
String name;
int age;
Person(this.name, this.age);
Person.fromJson(Map<String, dynamic> json){
name = json['name'];
age = json['age'];
}
}
// 常量构造函数
class Animal{
final String name;
final int age;
const Animal(this.name, this.age);
}
void main(List<String> args) {
Point p = Point();
print(p.x); // 调用x的 Getter
p.y = 1; // 调用y的 Setter
print(p.y); // 调用y的 Getter
}
class Point{
int x,y;
}
void main(List<String> args) {
Point p = Point.origin();
print(p.x); // 0
print(p.y); // 1
}
class Point{
int x,y;
Point(this.x, this.y);
// 命名式构造函数
Point.origin(){
x = 0;
y = 1;
}
}
调用顺序
传递给父类构造函数的参数不能使用 this 关键字。
使用(:)为子类的构造函数指定一个父类的构造函数。
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {.
// Person没有默认构造函数
// 需要通过 super.fromJson 来显示调用
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// 打印:
// in Person 先执行父类的构造
// in Employee
if (emp is Person) { // emp类继承了Person
emp.firstName = 'Bob';
}
print(emp.firstName); // Bob
(emp as Person).firstName = 'Jack';
print(emp.firstName); // Jack
}
class Person {
String firstName;
// 初始化列表 会比 构造函数优先执行
Person.fromJson(Map data): firstName = data['firstName'] {
print(firstName);
}
}
main() {
Person p = Person.fromJson({ 'firstName': 'zhangsan'});
}
设置final 字段
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
// 初始化列表设置final属性,非常好用
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin); // 3.605551275463989
}
void main(List<String> args) {}
class Point {
int x, y;
Point(this.x, this.y);
// 重定向构造函数
// 在函数中调用另一个构造函数的形式
Point.origin(int num) : this(num, 0);
}
void main(List<String> args) {
Point p = const Point(0, 0);
Point p2 = const Point(0, 0);
Point p3 = Point(0, 0);
// 这两个实例对象是相同的
print(identical(p, p2)); // true
// 如果不使用const声明实例,则不会相等
print(identical(p, p3)); // false
}
class Point {
// 变量必须用final 定义
final num x, y;
const Point(this.x, this.y); // 构造函数也是常量
}
void main(List<String> args) {
Person p = Person('tom');
p.say(); // tom
}
class Person{
String name;
// 必须static 定义
static final Map<String, dynamic> _cach = Map<String, dynamic>();
factory Person(String name){
return _cach.putIfAbsent(name, () => Person._init(name));
}
Person._init(this.name);
void say(){
print(name);
}
}
对象的实例方法可以访问实例变量和this
。
void main(List<String> args) {
Person p = Person('tom', 'hello title');
p.say();
}
class Person{
String name;
String title;
Person(this.name, this.title);
void say(){
// 可以访问变量
print('name is $name');
// 也可以访问this
print(this.name);
}
}
你可以使用 get 和 set 关键字为额外的属性添加 Getter 和 Setter 方法
void main(List<String> args) {
Point p = Point(1, 2, 3);
print(p.point); // 6
p.point = 0;
print(p.point);
print(p.z);
}
class Point {
int x, y, z;
Point(this.x, this.y, this.z);
get point => x + y + z;
// TODO: 这里为啥设置point 却返回z的值?
set point(int num) => z = num + x;
}
void main(List<String> args) {
}
// 定义抽象类
abstract class Person{
// 定义抽象方法
void doSomething();
}
class Zhangsan extends Person{
// 实现具体的方法
void doSomething(){
}
}
void main(List<String> args) {
var me = Me();
me.sayHello();
}
abstract class Person{
String name;
int age;
void sayHello();
}
class Me extends Person{
void sayHello(){
print('hello');
}
}
一个类可以通过关键字 implements 来实现一个或多个接口并实现每个接口定义的 API。
void main(List<String> args) {
print(saySomething(Person('张三')));
print(saySomething(Man()));
}
String saySomething(Person person) => person.sayName('李四');
class Person {
String _name;
Person(this._name);
String sayName(String name) => '$_name,你好。我是$name';
}
class Man implements Person {
get _name => '谁也不是';
set _name(String name) => ''; // 因为存在隐式的setter,所以这个也要定义
String sayName(String name) => '$_name,你好。我是$name';
}
void main(List<String> args) {
Man man = Man();
man.sayName();
}
class Person{
void sayName() => print('hello person');
}
class Man extends Person{
void sayName() => super.sayName(); // 调用父类方法
}
重写类成员
void main(List<String> args) {
Man man = Man();
man.sayName();
}
class Person{
void sayName() => print('hello person');
}
class Man extends Person{
@override
void sayName() => print('hello man'); // 重写实例方法
}
重写运算符
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// 运算符 == 和 hashCode 的实现未在这里展示,详情请查看下方说明。
// ···
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
noSuchMethod
这个地方没有看明白
void main(List<String> args) {
Man man = Man();
// man.name;
// todo 怎么使用??
}
class Person {
void sayName() => print('hello person');
}
class Man extends Person {
void sayName() => super.sayName(); // 调用父类方法
@override
void noSuchMethod(Invocation invocation) {
print('你尝试使用一个不存在的成员:' + '${invocation.memberName}');
}
}
使用枚举
void main(List<String> args) {
print(Color.blue); // 获取枚举
print(Color.red.index); // 获取枚举下标
List<Color> colors = Color.values; // 获取全部枚举
print(colors[2]);
}
enum Color{ // 定义枚举
red, blue, green
}
switch枚举
void main(List<String> args) {
var aColor = Color.red;
// 如果使用switch 则枚举中的每一个成员都得用case判断
// 否则就会发出警告
switch (aColor) {
case Color.red:
print('红色');
break;
case Color.blue:
print('蓝色');
break;
case Color.green:
print('绿色');
break;
}
}
enum Color {
// 定义枚举
red,
blue,
green
}
覆写操作符基本格式:
返回类型 operator 操作符(参数1,参数2...){
实现体...
return 返回值
}
void main(List<String> args) {
Musical musical = Musical();
musical.doSomethin();
}
mixin Person {
bool canCook = true;
bool canSay = false;
// mixin 模式不可以定义构造函数
// Person();
void doSomethin() {
if (canCook == true) {
print('可以做饭');
} else if (canSay == true) {
print('可以说话');
}
}
}
class Musical with Person{
@override
void doSomethin() {
// TODO: implement doSomethin
super.doSomethin(); // 直接调用父类
print('我是子类哦');
}
}
静态变量
void main(List<String> args) {
print(Person.name); // test static
}
class Person{
static final String name = 'test static';
}
静态方法
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
// 对于一些通用或常用的静态方法,应该将其定义为顶级函数而非静态方法。
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
代码错误提示
void main(List<String> args) {
var names = List<String>(); // 声明为字符串数组,一旦不是则报错
names.addAll(['Seth', 'Kathy', 'Lars']);
// 提示报错
// names.add(42); // Error
}
减少重复代码 使用泛型声明一个类,让不同类型的缓存实现该类做出不同的具体实现。
void main(List<String> args) {}
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
class Acache extends Cache<String> {
String getByKey(String key) {
// 具体实现时指定
return 'hello';
}
void setByKey(String key, String value) {
// 具体实现时指定
print(11);
}
}
void main(List<String> args) {
List list = <String>['1', '2', '3']; // 字符串集合
Set set = <String>{'1','2','3'}; // 字符串集合
Map map = <String, int>{'age': 1, 'size':12}; // Map
}
void main(List<String> args) {
// 与字面量相对应,也可以通过构造函数的方式使用泛型
Map map = Map<String, int>();
}
void main(List<String> args) {
List list = List<String>();
// list.addAll(['1','2']);
// 如果此时使用addAll则会报错
list.add('1');
list.add('2');
print(list is List<String>); // true
var names = List<String>();
names.addAll(['小芸', '小芳', '小民']);
print(names is List<String>); // true
}
void main(List<String> args) {
var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
print(someBaseClassFoo.toString()); // 'Foo<SomeBaseClass>' 的实例
print(extenderFoo.toString()); // 'Foo<Extender>' 的实例
// 如果不指定泛型,默认是SomeBaseClass
var foo = Foo();
print(foo);
// 将非 SomeBaseClass 的类型作为泛型参数则会导致编译错误
// var foo = Foo<Object>();
}
class SomeBaseClass {}
// 这里的T,其实可以随意指定。一般是T、E、S、K等
class Foo<T extends SomeBaseClass> {
// 具体实现……
String toString() => "'Foo<$T>' 的实例";
}
class Extender extends SomeBaseClass {}
void main(List<String> args) {
var list = List<String>();
list.addAll(['1','2']);
var firstValue = first(list);
print(firstValue); // 1
}
T first<T>(List<T> ts) {
// 处理一些初始化工作或错误检测……
T tmp = ts[0];
// 处理一些额外的检查……
return tmp;
}
void main(List<String> args) {}
// async 与 await同时使用
Future checkVersion() async {
// 通过 try-catch 捕获异常
try {
var version = await lookUpVersion();
} catch (e) {
// 无法找到版本时做出的反应
}
}
void lookUpVersion() {}
void main(List<String> args) {
}
// 普通函数直接添加async关键字即可
Future<String> lookUpVersion() async => '1.0.0';
通过实现类的 call() 方法,允许使用类似函数调用的方式来使用该类的实例。
// WannabeFunction 类定义了一个 call() 函数,函数接受三个字符串参数,函数体将三个字符串拼接,字符串间用空格分割,并在结尾附加了一个感叹号
class WannabeFunction {
String call(String a, String b, String c) => '$a $b $c!';
}
var wf = WannabeFunction();
var out = wf('Hi', 'there,', 'gang');
main() => print(out);
制作的思维导图,加深学习印象。如有错误欢迎指正。
原始图片比较大,为了保证打开速度只上传了一张截图。如果需要高清图片可以在我的源码「https://github.com/siberiawolf/dart_study」文件中找到。
思维导图 (完结)
参考资料: