Dart 的使用
安装配置
1.使用Dart 语言 首先需要配置Dart环境,那么我们就需要下载 dart SDK ,然后找到bin文件夹路径,配置到环境变量
2.编辑器的选择,我们用什么去书写dart。 选择vscode ,可以安装插件 dart ,后续还会用到flutter ,因此一起安装,方便运行编译,安装下 run code插件
简单使用
1.dart 的入口是main函数
2.在dart中打印内容使用print
3.dart中函数的定义
4.main函数参数的作用和使用方法
变量声明
1.明确推到
- 类型 变量名称 = 赋值
2.类型推倒
- var / const / finall / dynamic
- 区别 var声明后可以改变变量,但是类型不能改变
- const 是声明一个常量,且这个常量只能通过 直接得到,不能推倒得出
- finall 也是声明一个常量,但是这个常量可以推倒得出,比如函数
- dynamic 声明一个变量, 变量可以改变,并且可以改变变量类型
字符串和数字之间的转换
-
字符串和数字转换
-
var one = int.parse('111'); var two = double.parse('12.22'); print('${one} ${one.runtimeType}'); // 111 int print('${two} ${two.runtimeType}'); // 12.22 double
-
-
数字转字符串
-
var num1 = 123; var num2 = 123.456; var num1Str = num1.toString(); var num2Str = num2.toString(); var num2StrD = num2.toStringAsFixed(2); // 保留两位小数 print('${num1Str} ${num1Str.runtimeType}'); // 123 String print('${num2Str} ${num2Str.runtimeType}'); // 123.456 String print('${num2StrD} ${num2StrD.runtimeType}'); // 123.46 String
-
-
Bool类型
- dart中没有非 0 即真的写法
- dart 中也没有 非空即真的写法
-
字符串类型
-
字符串的定义方式
-
var message1 = 'hello world'; var message2 = 'hello fultter'; var message3 = '''abc cba bac''';
-
-
字符串的拼接
-
final name = 'why'; final age = 18; final height = 1.88; print("name":$name age:$age height:$height);
-
-
-
集合类型
-
List类型
-
// 1.List 类型 ['元素1','元素2','元素3'] List<String> names = ['alger', 'jams', 'kobe', 'alger', 'jams']; // 1.1 数组去重 List<String> names1 = []; for (String name in names) { print(name); if (!names1.contains(name)) { names1.add(name); } } print(names1); // 1.2数组去重 List<String> names2 = List.from(Set.from(names)); print(names2);
-
2.Set 类型
// 使用场景 对list 元素进行去重 Set<int> ages = {1, 2, 23, 3, 3};
-
3.map 类型
-
Map<String, dynamic> fruits = {'苹果': 1, '香蕉': 2, '梨子': true}; print(fruits['苹果']);
-
-
集合的常见操作
-
获取集合的长度
letters.length
-
对于List而言,由于元素是有序的,他还提供了一个删除索引位置上元素的方法
// 添加/删除/包含元素 numbers.add(5); numbersSet.add(5); print('$numbers $numbersSet'); numbers.remove(1); numbersSet.remove(1); print('$numbers $numbersSet'); print(numbers.contains(2)); print(numbersSet.contains(2)); // List根据index删除元素 numbers.removeAt(3); print('$numbers');
-
-
Map的操作
由于它有key和value,因此无论是读取值,还是操作,都要明确是基于key的,还是基于value的,或者是基于key/value对的。
// Map的操作 // 1.根据key获取value print(infoMap1['name']); // why // 2.获取所有的entries print('${infoMap1.entries} ${infoMap1.entries.runtimeType}'); // (MapEntry(name: why), MapEntry(age: 18)) MappedIterable<String, MapEntry<String, Object>> // 3.获取所有的keys print('${infoMap1.keys} ${infoMap1.keys.runtimeType}'); // (name, age) _CompactIterable<String> // 4.获取所有的values print('${infoMap1.values} ${infoMap1.values.runtimeType}'); // (why, 18) _CompactIterable<Object> // 5.判断是否包含某个key或者value print('${infoMap1.containsKey('age')} ${infoMap1.containsValue(18)}'); // true true // 6.根据key删除元素 infoMap1.remove('age'); print('${infoMap1}'); // {name: why}
函数
-
函数的基本定义
Dart 是一种真正的面向对象语言,所以即使函数也是对象,所以也有类型,类型就是Function. 这样就意味着函数可以作为变量定义或者作为其他函数的参数或者返回值
-
函数的定义方式
返回值类型 函数的名称(参数列表){ 函数体 return 返回值 }
按照上面的定义方式,我们定义一个完整的函数
int sum(num num1, num num2){ return num1 + num2; }
另外,如果函数中只有一个表达式,那么可以使用箭头语法
注意,这里面只能是一个表达式,不能是一个语句
sum(num2,num2) => num1 + num2
-
函数的参数问题
- 函数的参数可以分成两类:必须参数 和 可选参数
- 前面使用的参数都是必须参数
-
可选参数
-
可选参数可以 分为
命名可选参数
和位置可选参数
- 命名可选参数用 { } 位置可选参数 用 [ ]
-
命名可选参数: {param1, param2, ...} 位置可选参数: [param1, param2, ...]
-
// 命名可选参数 printInfo1(String name, {int age, double height}) { print('name=$name age=$age height=$height'); } // 调用printInfo1函数 printInfo1('why'); // name=why age=null height=null printInfo1('why', age: 18); // name=why age=18 height=null printInfo1('why', age: 18, height: 1.88); // name=why age=18 height=1.88 printInfo1('why', height: 1.88); // name=why age=null height=1.88 // 位置可选参数 定义位置可选参数 printInfo2(String name, [int age, double height]) { print('name=$name age=$age height=$height'); } // 调用printInfo2函数 printInfo2('why'); // name=why age=null height=null printInfo2('why', 18); // name=why age=18 height=null printInfo2('why', 18, 1.88); // name=why age=18 height=1.88
-
参数可以有默认值,在不穿如的情况下,使用默认值
-
注意,只有可选参数才可以有默认值,必须参数不能有默认值
-
// 参数的默认值 printInfo4(String name, {int age = 18, double height=1.88}) { print('name=$name age=$age height=$height'); }
-
-
-
函数是一等公民
-
在很多语言中,函数并不能作为一等公民来使用,比如 Java 、 oc 这种限制让编程不够灵活,所以现代编程语言基本都支持函数作为一等公民来使用 Dart也支持
这就意味着你可以将函数赋值给一个变量,也可以将函数作为另一个函数的参数或者返回值来使用
main(List<String> args) { // 1.将函数赋值给一个变量 var bar = foo; print(bar); // 2.将函数作为另一个函数的参数 test(foo); // 3.将函数作为另一个函数的返回值 var func =getFunc(); func('kobe'); } // 1.定义一个函数 foo(String name) { print('传入的name:$name'); } // 2.将函数作为另外一个函数的参数 test(Function func) { func('coderwhy'); } // 3.将函数作为另一个函数的返回值 getFunc() { return foo; }
-
-
匿名函数的使用
- 大部分我们定义的函数都会有自己的名字,比如前面定义的foo . test函数等
- 但是某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数 ,也可以叫 lamda 或者 closure
main(List<String> args) { // 1.定义数组 var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游']; // 2.使用forEach遍历: 有名字的函数 printElement(item) { print(item); } movies.forEach(printElement); // 3.使用forEach遍历: 匿名函数 movies.forEach((item) { print(item); }); movies.forEach((item) => print(item)); }
运算符
-
除法、整除、取模运算
var num = 7; print(num / 3); // 除法操作, 结果2.3333.. print(num ~/ 3); // 整除操作, 结果2; print(num % 3); // 取模操作, 结果1;
-
??= 赋值操作 (有点三目运算符的味道)
当变量null时,使用后面的内容进行赋值
当变量有值时,使用自己原来的值
-
main(List<String> args) { var name1 = 'coderwhy'; print(name1); // var name2 = 'kobe'; var name2 = null; name2 ??= 'james'; print(name2); // 当name2初始化为kobe时,结果为kobe,当初始化为null时,赋值了james }
-
条件运算符
Dart 中包含一致比较特殊的条件运算符 : expr1 ?? expr2
如果expr1 是 null ,则返回expr2的结果
如果expr1 不是 null ,直接使用expr1的结果
var temp = 'why'; var temp = null; var name = temp ?? 'kobe'; print(name);
-
级联语法: …
-
某些使用,我们希望对一个对象进行连续的操作,这个可以使用级联语法
-
class Person { String name; void run() { print("${name} is running"); } void eat() { print("${name} is eating"); } void swim() { print("${name} is swimming"); } } main(List<String> args) { final p1 = Person(); p1.name = 'why'; p1.run(); p1.eat(); p1.swim(); final p2 = Person() ..name = "why" ..run() ..eat() ..swim(); }
-
-
if 和 else
!!!!用法跟 JS中一致,但是不支持非空即真或者 非0即真,必须明确的bool类型
-
循环操作 for , for in , while , do - while
-
switch - case !!!注意:每个case语句,默认情况下必须以一个break结尾,防止case穿透
类和对象
类的定义
-
在Dart中,定义类 用class关键字
-
类通常有两部分组成:成员(member) 和 方法 (method)
-
class 类名 { 类型 成员名: 返回值类型 方法名(参数列表) { 方法体 } }
- 这里又一个注意点:我们在方法中使用属性(成员/实例变量)时,并没有加this;
- Dart 的开发风格中,在方法通常使用属性时,会省略this, 但是有命名冲突时候,this不能省略
构造方法
我们知道,当通过类创建一个对象时,会调用这个类的构造方法
-
当类中没有明确的构造方法时,将默认拥有一个无参的构造方法
-
前面的Person 中我们就是在调用这个构造方法
我们也可以根据自己的需求,定义自己的构造方法
-
注意一: 当有了自己的构造方法时,默认的构造方法将会失效,不能使用
- 当然,你可能希望明确的写一个默认的构造方法,但是会和我们自定义的构造方法冲突
- 这是因为Dart本身不支持函数的重载(名称相同,参数不同的方式)
-
注意二:这里我还实现了 toString方法
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@override
String toString() {
return 'name=$name age=$age';
}
}
另外,在实现构造方法时,童话村做的事情就是通过 **参数 ** 给 属性 赋值. 为了简化这一过程,Dart提供了一种更加简洁的语法糖形式
Person(String name, int age) {
this.name = name;
this.age = age;
}
// 等同于
Person(this.name, this.age);
命名构造方法
开发中我们需要用到更多的构造方法,但是由于dart不支持函数重载,所以我们不能够创建相同名称的构造方法,那就创建不同的
class Person {
String name;
int age;
Person() {
name = '';
age = 0;
}
// 命名构造方法
Person.withArgments(String name, int age) {
this.name = name;
this.age = age;
}
@override
String toString() {
return 'name=$name age=$age';
}
}
// 创建对象
var p1 = new Person();
print(p1);
var p2 = new Person.withArgments('why', 18);
print(p2);
// 比如map转成对象,可以提供如下的构造方法
// 新的构造方法
Person.fromMap(Map<String, Object> map) {
this.name = map['name'];
this.age = map['age'];
}
// 通过上面的构造方法创建对象
var p3 = new Person.fromMap({'name': 'kobe', 'age': 30});
print(p3);
初始化列表
我们来重新定义一个陪 Point ,传入 x/y ,可以得到他们的距离 distance
class Point {
final num x;
final num y;
final num distance;
// 错误写法
// Point(this.x, this.y) {
// distance = sqrt(x * x + y * y);
// }
// 正确的写法
Point(this.x, this.y) : distance = sqrt(x * x + y * y);
}
重定向构造方法
在某些情况下, 我们希望在一个构造方法中去调用另外一个构造方法, 这个时候可以使用重定向构造方法
:在一个构造函数中,去调用另外一个构造函数(注意:是在冒号后面使用this调用)
class Person {
String name;
int age;
Person(this.name, this.age);
Person.fromName(String name) : this(name, 0);
}
常量构造方法
某些情况下,传入相同值时
,我们希望返回同一个对象
,这个时候,可以使用常量构造方法.默认情况下,创建对象时,即使传入相同的参数,创建出来的也不是同一个对象
main(List<String> args) {
var p1 = Person('why');
var p2 = Person('why');
print(identical(p1, p2)); // false
}
class Person {
String name;
Person(this.name);
}
但是, 如果将构造方法前加const进行修饰
,那么可以保证同一个参数,创建出来的对象是相同的
- 这样的构造方法就称之为
常量构造方法
。
main(List<String> args) {
var p1 = const Person('why');
var p2 = const Person('why');
print(identical(p1, p2)); // true
}
class Person {
final String name;
const Person(this.name);
}
常量构造方法有一些注意点:
-
注意一:**拥有常量构造方法的类中,所有的**成员变量必须是final修饰的.
-
注意二:
为了可以通过常量构造方法,创建出相同的对象,不再使用 new关键字,而是使用const关键字
- 如果是将结果赋值给const修饰的标识符时,const可以省略.
工厂构造方法
Dart提供了factory关键字, 用于通过工厂去获取对象
main(List<String> args) {
var p1 = Person('why');
var p2 = Person('why');
print(identical(p1, p2)); // true
}
class Person {
String name;
static final Map<String, Person> _cache = <String, Person>{};
factory Person(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final p = Person._internal(name);
_cache[name] = p;
return p;
}
}
Person._internal(this.name);
}