运算符
- 地板除(~/)
- 类型判断运算符(is | is!)判断某个变量是否属于某种类型
- 避空运算符(?? | ??=)
- 条件属性访问(?.)
- 级联运算符(…)
- myObject.myMethod(); //返回myMethod()的返回值
- myObject…myMethod()…myMethod2(); //返回myObject的引用
申明函数
- 直接声明不需要function关键字
- dart中的箭头函数只是函数的一种简写形式
- 匿名函数
- 立执行函数
// 申明函数
void printHello() {
print('hello world');
}
// 返回类型为int
int getNum() {
return 123;
}
// 匿名函数 箭头函数
var myPrint = (value) => {
print(value1);
}
-----------------------------------------------------
void main() {
printHello();
print(getNum());
myPrint('x');
// 立执行函数
((int n){
print(n)
})(12);
}
函数参数
- 必填参数
- 参数类型 参数名称
- 可选参数
- 放在必选参数后面
- 通过中括号包裹起来
- 带默认值的可选参数
- 命令参数
- 用大括号包裹起来
- 调用函数时,命名参数的名称与声明函数中的名称保持一致
- 函数参数
void main() {
String userInfo(String name, [int age = 18], { int gender = 0 }) {
return 'name: $name, 年龄: $age';
}
String res = userInfo('max', 20, gender: 1);
print(res);
const myPrint = (res) => {
print(res)
}
List l = [1, 2, 3]
l.forEach(myPrint)
}
作用域和闭包
和js一样
异步函数
- JS中,异步调用通过Promise 实现
- async 函数返回一个Promise,await 用于等待 Promise
- Dart中,异步调用通过Future 实现
- async 函数返回一个Future,await 用于等待 Future
import 'package:http/http.dart' as http; //pub.dev 类似npm
Future getdata() {
final url = 'https://httpbin.org/ip';
return http.get(url).then(res => {
print(res.body);
String ip = jsonDecode(res.body)['origin'];
return ip;
}).catch(err => {
print(err);
})
}
Future getdata() async {
final url = 'https://httpbin.org/ip';
final res = await http.get(url)
String ip = jsonDecode(res.body)['origin'];
return ip;
}
类
- 类是通过 class 声明的代码段,包含属性和方法。
- 属性:用来描述类的变量
- 方法:类中的函数称为类的方法
- 对象是类的实例化结果
- 编程方式
- dart 是面向对象的编程语言(OOP)
- Js 是面向过程的编程语言(POP)
class Person {
String name = 'lys';
void getInfo() {
print('我是:$name')
}
}
void main() {
Persion p = new Persion(); //实例化
// 访问属性
print(p.name)
// 访问方法
p.getInfo()
// Dart 中所有内容都是对象
Map m = new Map();
print(m.length);
m.addAll({ 'name': 'aaa', 'age': 14 })
}
构造函数
- 默认构造函数
- 与类同名的函数,在实例化时,自动被调用
- 命名构造函数
- 在类中使用命名构造器(类名.函数名)实现多个构造器,可以提供额外的清晰度(new Point.origin())
- 常量构造函数
- 如果类生成的对象不会改变,可以通过常量构造函数使这些对象成为编译时常量
- 工厂构造函数(单例模式)
- 工厂函数不能进行实例化操作
class Person {
String name;
static Person instance;
factory Person([String name = 'maxloong']) {
if(Person.instance == null) {
// 第一次实例化
Person.instance = new Person.newSelf(name);
}
return Person.instance;
}
// 命名构造函数
Person.newSelf(this.name);
}
访问修饰符
- Dart和Typescript不一样,没有访问修饰符(public,protected,private,readonly)
- Dart类中,默认的访问修饰符是public
- 如果属性或方法以_(下划线)开头,则表示私有private
- 只有把类单独抽离出去,私有属性和方法才起作用
Getter和Setter
- Getter(获取器)是通过get关键字修饰的方法
- 函数没有小括号,访问时也没有小括号(像访问属性一样访问方法)
- Setter(修改器)是通过set关键字修饰的方法
- 访问时,像设置属性一样给函数传参
初始化列表
- 作用:在构造函数中设置属性的默认值
- 时机:在构造函数体执行之前执行
- 语法:使用逗号分隔初始化表达式
- 场景:常用于设置final常量的值
class Rect {
int height;
int width;
Rect(): height = 2, width = 10 {
print(this.width, this.height);
}
getArea() {
return this.height * this.width;
}
}
static
- static 关键字可以指定静态成员
- 静态属性
- 静态方法
- 静态成员可以通过类名称直接访问(无需实例化)
- 实例化是比较消耗资源的,声明静态成员,可以提高程序性能
- 静态方法不能访问非静态成员,非静态方法可以访问静态成员
- 静态方法中不能使用this关键字
- 不能使用this关键字,访问静态属性
元数据
- 元数据以@开头,可以给代码标记一些额外的信息
- 元数据可以用来库,类,构造器,函数,字段,参数或变量声明的前面
- @override(重写)
- 某些方法添加该注释后,表示重写了父类中的同名方法
- @required(必填)
- 可以通过@required来注解Dart中的命名参数,用来指示它是必填参数
- @deprecated(弃用)
- 若某类或某方法加上该注解之后,表示此方法或类不再建议使用
继承
- 根据类的先后顺序,可以将类分为父类和子类
- 子类通过extends 关键字继承父类
- 继承后,子类可以使用父类中,可见的内容(属性或方法)
- 子类可以通过@override元数据来标记重写父类方法
- 子类当中,可以通过Super关键字来引用父类中,可见的内容
- 属性
- 方法(普通构造函数,命名构造函数)
抽象类
- 抽象类是用abstract关键字修饰的类
- 抽象类的作用是充当普通类的模板,约定一些必要的属性和方法
- 抽象方法是指没有方法体的方法
- 抽象类中一般都有抽象方法,也可以没有抽象方法
- 普通类中,不能有抽象方法
- 抽象类不能被实例化
- 抽象类可以被普通类继承
- 如果普通类继承抽象类,必须实现抽象类中所有的抽象方法
- 抽象类还可以充当接口被实现
- 如果把抽象类当做借口实现的话,普通类必须得实现抽象类李敏啊定义的所有属性和方法
接口
- 接口在Dart中就是一个类(只是用法不同)
- 与java不同,java中的接口需要用interface关键字声明;Dart中不需要
- 接口可以是任意类,但一般使用抽象类做接口
- 一个类可以实现多个接口,多个接口用逗号分隔
- class MyClass impleimplements Interface1,Interface2 { … }
- 接口可以堪称一个个小零件。类实现接口就相当于组装零件
- 普通类实现接口后,必须重写接口所有的属性和方法
abstract class Processor {
String cores;
arch(String name);
}
abstract class Camera {
String resolution;
brand(String name);
}
class Phone implements Processor, Camera {
String cores;
String resolution;
arch(String name) {
print(0, name)
}
brand(String name) {
print(1, name)
}
}
void main() {
}
泛型
-
泛型指的是 在函数,类,接口中指定宽泛数据类型的语法
- 泛型函数
- 泛型类
- 泛型接口
-
通常,在尖括号中,使用一个字母来代表类型,例如E,T,S,K和V等
- 返回类型函数名<输入类型>(参数类型 参数){ 函数体 }
T getData<T>(T value) { return value; } getData<int>(12); getData<String>("12");
-
使用泛型减少重复代码
-
范型函数
T getData<T>(T value) { return value; }
-
泛型类
// 普通 class CommonClass { Set s = new Set<int>(); void add(int value) { this.s.add(value); } void info() { print(this.s); } } void main() { CommonClass c = new CommonClass(); c.add(1); c.info(); GenericsClass g = new GenericsClass<String>(); g.add("1"); g.info(); } // 泛型类 class GenericsClass<T> { Set s = new Set<T>(); void add(T value) { this.s.add(value); } void info() { print(this.s); } }
-
泛型接口
abstract class ObjCache { getBykey(String key); void setBykey(String key, Object value); } abstract class StringCache { getBykey(String key); void setBykey(String key, String value); } abstract class Cache<T> { getBykey(String key); void setBykey(String key, T value); } // 文件缓存 class FileCache<T> implements Cache<T> { getBykey(String key) { return null; }; void setBykey(String key, T value) { print("文件缓存"); }; } // 内存缓存 class MemoryCache<T> implements Cache<T> { getBykey(String key) { return null; }; void setBykey(String key, T value) { print("文件缓存"); }; } void main() { FileCache fc = new FileCache<String>(); fc.setBykey('foo', 'bar'); FileCache fc = new FileCache<Map>(); fc.setBykey('index', {name: '张三丰'}); MemoryCache mc = new MemoryCache<String>(); mc.setBykey('foo', 'bar'); }
-
泛型类型限制
class SomeBaseClass { // ... } class Foo<T extends SomeBaseClass> { String toString() => "Instance of 'Foo<$T>'"; } void main() { var someBaseClassFoo = Foo<SomeBaseClass>(); print(someBaseClassFoo); }
枚举
- 枚举是数量固定的常量值,通过enum关键字声明
- enum Color { red, green, blue }
- 枚举的values 常量,可以获取所有枚举值列表
- List colors = Color.values;
- 可以通过index获取值的索引
- assert(Color.green.index === 1);