Flutter基础 Dart语法(1)

563 阅读5分钟

一、 Hello Dart

1.1 Hello World

在VSCode中新建一个helloWorld.dart文件,添加下面的内容

main(List<String> args){
 print('Hello World');
}

然后运行代码,就可以看到Hello World 的结果

1.2 程序的分析

  • Dart语言的入口也是main函数,并且必须显示的进行定义;

  • Dart的入口函数 main 是没有返回值的

  • 方法在没有返回值的时候是可以省略void

  • 传递给main 的命令行参数,是通过List<String> 完成的

    从字面上可以理解List是Dart中的集合类型 其中的每一个String都便是传递给 main的一个参数

  • 定义字符串的时候,可以使用单引号或者双引号

  • 每行语句必须使用分号结尾,很多语言并不需要分号,比如Swift

二、 定义变量

1.1 明确声明(Explicit)

明确声明变量的方式,格式如下:

变量类型  变量名称 = 赋值;

示例代码:

    String name = "Maybe";
    print(name);
    
    int age = 18;
    print(age);

    double height = 24.5;
    print(height);

    // print("$name,$age,$height");
    print("一个人${name}${age}${height}");

注意事项:定义的变量可以修改值,但是不能赋值其他的类型

 name = 11;  //error 定义的变量可以重新赋值,但是不能赋值其他类型

1.2 类型推导(Type Inference)

类型推导申明变量的方式,格式如下:

var/dynamic/const/final 变量名 = 赋值;

在Dart语法中,没有初始化的变量自动获取一个默认值为NUll,一切皆对象,对象的默认值为Null

    var thisNull;
    print("$thisNull,thisNull的类型 ${thisNull.runtimeType}");

上面的代码输出

null,thisNull的类型 Null

1.2.1 var的使用

var的使用示例

  • runtimeType 用于获取变量当前的类型
    var type1 = 1;  //申明变量
     print("当前type1的类型 ${type1.runtimeType}"); /*用于获取变量当前的类型*/

var的错误用法:

type1 = "2"; //不可以将一个String赋值给一个int类型

1.2.2 dynamic的使用

在开发中,通常情况下不是用dynamic来申明变量

   print("改变前type2的变量类型 ${type2.runtimeType}");
   type2 = 1;
   print("改变后type2的变量类型 ${type2.runtimeType}");

在这里,使用dynamic申明的变量,重新赋值之后,会改变变量的类型

1.2.3 final&const的使用

final、 const 都是用于定义常量的,也就是定义之后不可以做修改

   const type3 = "3";   //申明常量
   final type4 = "type4";//申明常量
   
   type3 = "4";      //错误
   type4 = "type3";  //错误
   

在这里会报错

Error: Can't assign to the const variable 'type3'. 不能赋值给type3

Error: Can't assign to the final variable 'type4'. 不能赋值给type4

final 和 const有什么区别呢

  • const在赋值时,赋值的内容必须是在编译期间就确定的,也就是写死的
  • final在赋值时,可以动态获取,比如赋值一个函数
String getName() {
 return "Maybe";
}
  
   const getName1 = getName(); //在这里会报错,
   final getName2 = getName();

  • final 和 const 一旦被赋值,有确定的结果,就不会被再次赋值
    final date1 = DateTime.now();
    print("当前时间 $date1");
    sleep(Duration(seconds:2));
    print("睡眠后的时间 date1:$date1");
    final date2  = DateTime.now();
    print("没有睡眠后的时间 date2:$date2");
    
    当前时间 2020-05-30 14:03:28.271718
    睡眠后的时间 date1:2020-05-30 14:03:28.271718
    没有睡眠后的时间 date2:2020-05-30 14:03:30.277818

  • const放在赋值语句的右边,可以共享对象,提高性能
class Person{
  const Person();
}

    final a = const Person();
    final b = const Person();
    print(identical(a,b));  //true
    
    final a =  Person();
    final b =  Person();
    print(identical(a,b)); //flase

三、 数字类型

3.1 数字类型

对于数值来说,我们也不用关心他是否有符号,以及数据的宽度和精度等问题。只需要整型用int,浮点型用double就行

在Dart中的 intdouble 可表示的范围并不是固定的,它取决于运行Dart的平台

main(List<String> args) {
  /*整数类型  int*/
  int age = 18;
  int hexAge = 0x12;
  print(age);
  print(hexAge);
 /*浮点型 double*/
 double height = 1.88;
 print(height);

 //字符串转数字
 var a = int.parse('1111');
 var b = double.parse('22.22');
 print('a的数据类型 ${a.runtimeType},a的值 $a' );//a的数据类型 int,a的值 1111
 print('b的数据类型 ${b.runtimeType},b的值 $b' );//b的数据类型 double,b的值 22.22

//数字转字符串
 var num1 = 123;
 var num2 = 456.789;
 var num3 = 1.234567890123;
 var num4 = 2.456788656898;
 var num1Str = num1.toString(); //num1Str的数据类型 String,num1Str的值 123
 var num2Str = num2.toString(); //num2Str的数据类型 String,num2Str的值 456.789
 var num2StrD = num2.toStringAsFixed(2); //保留2位小数,num2StrD的数据类型 String,num2StrD的值 456.79  我发现会四舍五入,这里不是简单的截取 如果 num2 = 456.781 num2StrD的值为 456.78
 var num3Str = num3.toStringAsExponential(3); //指数
 var num4Str = num4.toStringAsPrecision(4); //精度,也就是字符串的长度,不包含小数点,这里填4,输出 2.457
 
 print('num1Str的数据类型 ${num1Str.runtimeType},num1Str的值 $num1Str');
 print('num2Str的数据类型 ${num2Str.runtimeType},num2Str的值 $num2Str');
 print('num2StrD的数据类型 ${num2StrD.runtimeType},num2StrD的值 $num2StrD');
 print('num3Str的数据类型 ${num3Str.runtimeType},num3Str的值 $num3Str');
 print('num4Str的数据类型 ${num4Str.runtimeType},num4Str的值 $num4Str');

}

3.2 布尔类型

布尔类型中,Dart提供了一个bool的类型,取值为true 和 flase

 //布尔类型
 var isFlag = true;
 print('$isFlag ${isFlag.runtimeType}'); //true bool
 

注意:Dart中不能判断非0即为真,或者非空即真

Dart的类型安全性意味着你不能使用if(非booleanvalue)或者assert(非booleanValue)之类的代码

var message = 'Hello Dart';
 if(message){
    print('判断走了这里');
 } //Error: A value of type 'String' can't be assigned to a variable of type 'bool'.

 

3.3 字符串类型

Dart字符串是UTF-16编码单元的序列,你可以使用单引号或者双引号来创建一个字符串

var s1 = 'Hello Flutter';
  var s2 = "Hello Flutter";
  var s3 = 'Hello \'Flutter';
  var s4 = "Hello ' Flutter";
  var s5 = '''
         111
         222
         333
         444
  '''; //这个表示多行字符串

在这里可以使用3个单引号来表示多行的字符串

字符串和其他变量或者表达式拼接时,使用${expression},如果表达式是一个标识符,那么{}可以省略.

   print("s1 = $s1 s2 = $s2 s3 = $s3 s4 = $s4 s5 = ${s5}");         

3.4 集合类型

3.4.1 集合类型的定义

对于集合类型,Dart内置了常用的三种: List /Set /Map

3.4.1.1 List定义
  //List 定义
  //1、使用类型推导定义
  var list1 = ['a','b','c','d'];
  print('$list1, ${list1.runtimeType}'); //[a, b, c, d], List<String>
  //2、明确指定类型
  List<int> list2 = [1,2,3,4];
  print("$list2,${list2.runtimeType}"); //[1, 2, 3, 4],List<int>
  
3.4.1.2 set定义

Set定义类似List,Set与List不同的就是 Set是无序的,并且元素不重复

  var set1 = {1,2,3,4};
  print('$set1,${set1.runtimeType}');

  Set<String> set2 = {'小黑','小白','小灰'};
  print('$set2,${set2.runtimeType}');
  

在Set中如果元素相同,我认为是会直接无视后面的相同的元素,同时会警告: Two elements in a set literal shouldn't be equal. Change or remove the duplicate element.

3.4.1.3 Map定义
 //Map 也就是字典类型,键值对集合
  //使用类型推导定义
  var map1 = {'name':'Maybe','age':'18'};
  print('$map1,${map1.runtimeType}'); //{name: Maybe, age: 18},_InternalLinkedHashMap<String, String>

  Map<String,Object> map2 = {'height':'188','weight':'140'};
   print('$map2,${map2.runtimeType}');//{height: 188, weight: 140},_InternalLinkedHashMap<String,    Object>
   

3.4.1 集合的常见操作

3.4.1.1 获取集合的长度
  • 所有集合都支持获取其长度 length
  print('list1的长度,${list1.length}');//list1的长度,4
  print('set1的长度,${set1.length}'); //set1的长度,4
  print('map1的长度,${map1.length}');//map1的长度,2
  
3.4.1.2 添加/删除/包含操作
  • 对于List 而言,由于元素是有序的,他提供了一个删除指定索引位置上的元素方法

常见的List的一些操作

  list1.add('f');
  list2.add(5);
  print('List增加 $list1,$list2'); //List增加 [a, b, c, d, f],[1, 2, 3, 4, 5]
   //在这里会报错 list2 是一个int类型的,他无法加入到一个string的list里面
  //list1.addAll(list2); //Error: The argument type 'List<int>' can't be assigned to the parameter type 'Iterable<String>'.
  
  list1.addAll(list3);//点击addAll这个方法进入官方文档可以看到注解:1.将[iterable]的所有对象追加到该列表的末尾;2.根据[iterable]中的对象数量来扩展列表的长度 ; 3. 如果该列表是固定长度的,则抛出[UnsupportedError]
  print('拼接后的List$list1');// +++++++[a, b, c, d, f, x, y, z]
  
  list1.remove('a');  //list1 删除a 元素
  print('List指定删除某个元素 $list1'); //List指定删除某个元素 [b, c, d, f, x, y, z]
  
  //在这里可以看出 下标是从0 开始的
  list1.removeAt(1); // list1 删除下标为1 的元素
  print('List删除下标为1 的元素 $list1');//List删除下标为1 的元素 [b, d, f, x, y, z]

  list1.removeLast(); // list 删除最后一个元素
  print('List删除最后一个元素 $list1');//List删除最后一个元素 [b, d, f, x, y]
  
  list1.removeRange(0, 3); //
  print('List 删除 从 0 - 3 的元素 后得到的 $list1');

  // list1.removeWhere((element) => false);
  // list1.removeWhere((element) => 1);

  list1.contains(1); //是否包含某个元素,
  print('${list1.contains(1)}');//这里返回false,因为现有的list1 里面只有 x,y  所以返回flase
   

常见的 Map操作

  • 由于是key/value形式的,且是无序的,所以任何操作,都是需要明确是基于keyvalue或者是key/value.