一、Hello,world!
我们在VSCode中新建一个helloWorld.dart
文件,添加下面的代码:
main(List<String> args) {
print("hello world");
}
我们从上面也可以知道:
1、Dart语言的入口也是main
函数,而且是显示定义(Swift 不需要显示写明)
2、main
函数是没有返回值的
3、传递给main函数的参数是通过
List<String>`(包含String类型的集合(数组)类型)
4、定义字符串可以使用''
,也可以使用""
5、每一个语句的后面都需要跟;
(Swift 、JS 不需要, OC需要)
二、定义变量
1、明确声明
明确声明变量的方式, 格式如下:
变量类型 变量名 = 变量值;
示例代码:
int value = 10;
String title = "Dart is great";
double price = 3.14;
print('value is ${value}, price is ${price} title is ${title}');// OC使用%@作为占位符,而Swift使用\()较为类似
通过明确声明的变量是可以更改其值的,但是不可以赋值其他类型
2、 类型推导(Type Inference)
var/dynamic/const/final 变量名 = 变量值;(不同的修饰关键字 作用不同)
2.1 var
示例代码:
var name = '我是大神官';
name = "我是股神";
print(name);
print(name.runtimeType); //输出 String
注意:Dart 的
var
和Swift 的var
是不一样的。Dart的var
指的是通过首次赋值的类型来确定变量类型,而Swift的var
是声明可变变量
2.2 dynamic
示例代码:
dynamic name = '我是大神官';
name = "我是股神";
print(name);
print(name.runtimeType); //输出 String
name = 12138;
print(name);
print(name.runtimeType); //输出 Int
注意:类似
Any
类型,但是通常开发中最好少用,可能会有潜在的危险
2.3 const & final
相同点:
const
和 final
都是用于定义变量的,定义之后值都不可以修改
const int value = 10;
final String title = "那么";
不同点:
const
在赋值时, 赋值的内容必须是在编译期间就确定下来的final
在赋值时, 可以动态获取
main(List<String> args) {
print("hello world");
// 比如通过函数赋值
final name = getName();//正确
//const name = getName();报错
print(name);
}
String getName() {
return "name";
}
在类的常量构造函数时,会再次讲解下面const的含义
main(List<String> args) { print("hello world"); final a = Person(); final b = Person(); print(identical(a, b)); //false final c = const Person(); final d = const Person(); print(identical(c, d)); //true } class Person { const Person(); }
三、数据类型
1、数字类型
这些不同的语言大同小异,下面只讲解一些Dart特有的一些点:
- 字符串转数字
var one = int.parse("123");
var two = double.parse("3.1415");
print('one ${one} , type is ${one.runtimeType} \ntwo ${two} , type is ${two.runtimeType}');
- 数字转字符串
var num = 123;
var num2 = 3.1415;
var numStr = num.toString();
var num2Str = num2.toString();
var num2StrD = num2.toStringAsFixed(2); //保留两位小数
2、布尔类型
Dart提供了一个bool的类型, 取值为true
和false
var isFlag = true;
print('$isFlag ${isFlag.runtimeType}');
注意:和Swift一样,Dart是类型安全的语言,并不是非0 即真,或者非空即真
3、字符串类型
Dart字符串是UTF-16编码单元的序列。您可以使用单引号或双引号创建一个字符串。
var s1 = 'Hello World';
var s2 = "Hello Dart";
var s3 = 'Hello\'Fullter';
var s4 = "Hello'Fullter";
字符串与变量和表达式的拼接:👆前面已经有写过多次,但是需要补充一点:如果${expression}中expression为标识符,则可以省略
var name = 'coderwhy';
var age = 18;
var height = 1.88;
print('my name is ${name} , age is ${age}, height is $height, age add height is ${age + height}');
4、集合类型
常见的集合类型:List
、Map
、Set
(基本都差不多)
1.1 List
//类型推导
var numArr = [1, 2, 3];
//明确类型
List<int> number = [1, 2, 3];
1.2 Set
//类型推导
var numArr = {1, 2, 3};
//明确类型
Set<int> number = {1, 2, 3};
List和Set 就是
[]
和{}
的区别,不同点:Set
是无序的,并且元素是不重复的。
1.3 Map
类似OC的NSDictionary、Swift的Dictionaty
var info = {'name': '张三', 'age': 18};
print(info);
print(info.runtimeType); //Map<String, Object>
Map<String, Object> info2 = {'height': 1.88, 'width': 3.14};
print(info2);
print(info2.runtimeType); //Map<String, Object>
2.1 集合类型的常见操作
下面只简单介绍一下常用操作:
2.1.1 集合的长度
//1、 三种集合类型 都支持获取长度属性length
var numArr = [1, 2, 3, 4, 5];
var numSet = {1, 2, 3, 4, 5};
var numMap = {'index' : 1, 'value' : 2};
print(numArr.length);
print(numSet.length);
print(numMap.length);
2.1.2 List的常见操作:
// list 添加操作
numArr.insert(0, 0);//插入指定下标
numArr.add(8);//末尾增加元素
numArr.replaceRange(2, 3, [10, 11]);//替换区间数组
//更改指定位置的元素
numArr[0] = 10;
// list 删除操作
numArr.removeLast(); //删除末尾元素
numArr.removeAt(3); //删除指定下标的元素
numArr.remove(1); //删除指定元素
numArr.removeRange(1, 2); //删除区间元素
numArr.removeWhere((element) => element % 2 == 0); //删除符合条件的元素
//是否包含某元素
print(numArr.contains(2)); //true
2.1.3 Set的常见操作
因为Set是无序的,所以不能通过下标进行操作
// Set 添加操作
numSet.add(10);
// Set 删除操作
numSet.remove(2);
numSet.removeWhere((element) => element % 2 == 0);
//是否包含某元素
print(numSet.contains(2)); //true
2.1.4 Map的常见操作
//增加、修改值
numMap['index'] = 100;
//指定key对应的的value
print(numMap['index']);
//获取所有的entries
print(
'${numMap.entries}, ${numMap.entries.runtimeType}'); //(MapEntry(index: 1), MapEntry(value: 2)) MappedIterable<String, MapEntry<String, int>>
//获取所有key
print(numMap.keys);
//获取所有value
print(numMap.values);
//是否包含指定的key
print(numMap.containsKey('index'));
//是否包含指定的value
print(numMap.containsValue("2"));
//删除指定key - value
numMap.remove("index"); //删除
//以指定条件删除
numMap.removeWhere((key, value) => value % 2 == 0);
2.1.5 List、 Set的遍历
//数组的遍历
for (var i = 0; i < numArr.length; i++) {
print(numArr[i]);
}
for (var value in numArr) {
print(value);
}
numArr.forEach((element) {
print(element);
});
print(numArr.where((element) => element > 2).toList());//筛选符合条件的新数组
print(numArr.any((element) => element > 3)); //检查是否有符合条件的元素
print(numArr.every((element) => element > 3)); //检查是否每个元素都符合条件
2.1.6 Set的遍历
Set是无序的,所以无法通过下标进行操作,其余上述与List并无区别
for (var item in numMap.keys) {
print(item);
}
for (var item in numMap.values) {
print(item);
}
numMap.forEach((key, value) {
print("$key---$value");
});
var newList = numMap.values.where((element) => element == 2);
//判断map的值是否有张三,返回值bool
var checkAny = numMap.values.any((element) => element == 1);
//判断map的值是否全部为张三,返回值bool
var checkEvery = numMap.values.every((element) => element == "1");
四、函数
1、函数的定义
在Dart中,函数是"一等公民",同Swift一样,函数也是对象,类型为Function。意味着函数可以作为变量定义或者作为其他函数的参数或者返回值。
函数的定义:
返回值类型 函数名(参数列表) {
函数体
return 返回值;
}
下面根据上面的定义定义一个函数:
int sum(int num1, int num2) {
return num1 + num2;
}
接下来,我们可以省略参数类型:
int sum(num1, num2) {
return num1 + num2;
}
如果函数体只有一个表达式,可以使用箭头语法:
int sum(int num1, int num2) => num1 + num2;
注意:使用
=>
语法,函数体里面只能是一个表达式,并不是适用于语句sum(int num1, int num2) => print(num1); //报错
2、函数的参数
函数参数有两种:
- 必须参数
- 可选参数
2.1 必须参数
没啥好讲的,看上面 声明形参类型 形参名
2.2 可选参数
可选参数又分下面两种:
- 命名可选参数
- 位置可选参数
2.2.1 命名可选参数
main(List<String> args) {
getUserInfo("张三");
getUserInfo("张三", age: 20);
getUserInfo("张三", age: 20, weight: 30.0);
}
getUserInfo(String name, {int age, double weight}) {
print('name ${name}, age ${age}, weight ${weight}');
}
2.2.2 位置可选参数
main(List<String> args) {
getUserInfo("李四");
getUserInfo("李四", 35);
getUserInfo("李四", 35, 88.0);
}
getUserInfo(String name, [int age, double weight]) {
print('name ${name}, age ${age}, weight ${weight}');
}
从上面的示例来看,命名可选参数和位置可选参数的写法就是
[]
和{}
将可选参数包裹的方式但是在使用上来看,命名可选参数显然更符合编写方式,更易理解,前后顺序可以更换 而位置可选参数,需要严格按照命名顺序传参,参数位置不能更换
2.3 默认参数
参数可以有默认值,在不传入的情况下, 使用默认值
注意:只有可选参数才可以有默认值, 必须参数不能有默认值
getUserInfo(String name, {int age = 1, double weight = 0.0}) {
print('name ${name}, age ${age}, weight ${weight}');
}
3、 函数是”一等公民“
在很多语言中, 函数并不能作为一等公民来使用, 比如Java/OC. 这种限制让编程不够灵活, 所以现代的编程语言基本都支持函数作为一等公民来使用, Dart也支持.
main(List<String> args) {
var fn = foo;
fn("name");
test(foo);
var getFn = getFunc();
getFn("NAME");
}
// 1.定义一个函数
foo(String name) {
print('传入的name:$name');
}
// 2.将函数作为另外一个函数的参数
test(Function func) {
func('coderwhy');
}
// 3.将函数作为另一个函数的返回值
getFunc() {
return foo;
}
4、匿名函数
大部分我们定义的函数都会有自己的名字, 比如前面定义的foo、test函数等等。
但是某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数(anonymous function),也可以叫lambda或者closure。
// 1.定义数组
var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游'];
printElement(item) {
print(item);
}
// 2.使用forEach遍历: 传入一个有名字的函数
movies.forEach(printElement);
// 3.使用forEach遍历: 匿名函数
movies.forEach((item) {
print(item);
});
movies.forEach((item) => print(item));
5、词法作用域
dart中的词法有自己明确的作用域范围,它是根据代码的结构({})来决定作用域范围的
优先使用自己作用域中的变量,如果没有找到,则一层层向外查找。
var name = 'global';
main(List<String> args) {
// var name = 'main';
void foo() {
// var name = 'foo';
print(name);
}
foo();
}
6、词法闭包
闭包可以访问其词法范围内的变量,即使函数在其他地方被使用,也可以正常的访问。
makeAdder(num addBy) {
return (num i) {
return i + addBy;
};
}
var adder2 = makeAdder(2);
print(adder2(10)); // 12
print(adder2(6)); // 8
var adder5 = makeAdder(5);
print(adder5(10)); // 15
print(adder5(6)); // 11
类似OC和Swift的捕获变量(🤣)
7、返回值问题
所有函数都有返回值
如果没有指定返回值,则语句返回nul
l;隐式附加到函数体。