Dart入门语法

323 阅读7分钟

[TOC]

简介

​ Dart是谷歌开发的编程语言,后来被Ecma (ECMA-408)认定为标准 [1] 。它被用于web、服务器、移动应用 [2] 和物联网等领域的开发;

​ 它是flutter的编程语言。

​ 面向对象的、类定义的、单继承的语言。它的语法类似C语言,可以转译为JavaScript,因此可以支持web的开发。前后端开发皆可以支持。

初识dart

新建的flutter项目中,查看lib/main.dart, 初步看一下他的写法:

image-20210202095742129

dart特点

  • 支持import/export ,即导入模块/导出模块
  • 面向对象
  • 强类型
  • 支持异步

dart基础语法

学习参考:dart语法参考网站

变量

创建一个变量并进行初始化变量

// 变量仅存储对象引用
var name = 'bob'; 
// 动态变量,在运行时才检测类型
dynamic dynamicName = 'bob';
// 显式声明变量
String name = 'bob';
dynamicName = 1;
// dynamicName = dynamicName.toString() + '12e32w';
dynamicName =  '${dynamicName}12e32w';

如果不赋值的话,会被解析变量值为null

int lineCount;
assert(lineCount == null);

常量

Final 和 Const

 // Without a type annotation
final name = 'Bob';
final String nickname = 'Bobby';
// 压力单位 (dynes/cm2)
const bar = 1000000; 
const double atm = 1.01325 * bar;

Const 关键字不仅可以用于声明常量变量。 还可以用来创建常量值,

final bar = const [];
var foo = const [];
// 非 Final , 非 const 的变量是可以被修改的
foo = [1, 2, 3];

内建类型

Dart 语言支持以下内建类型:

  • Number
  • String
  • Boolean
  • Null
  • List (也被称为 Array)
  • Set Set 是一个元素唯一且无需的集合。
  • Map
  • Rune (用于在字符串中表示 Unicode 字符)
  • Symbol

Number/String/Boolean/List

intdouble 都是 num. 的亚类型。

// 数字整型
int lineCount=22; 
// 浮点型
double a=20; // 20.0
// 字符串
String name = 'bob'; 
// boolean类型
bool flag = true;
// null
var d = null;
d??print('d为空');// a??... a如果是空,则执行后面的代码

注意:上面的非空判断??是dart特有的

List

不指定泛型

var list = [1, 2, 3];

指定泛型

var list33 = <String>["a","b"];
List<String> list7 = ['a','b','3'];
List<String> list8 = new List(2);
list8[0]=('aaa');
print(list8);//[aaa, null]

常用属性

List<String> list13 = <String>["aaa","bbb""ccc"] ;
print(list13.length);//3    长度
 print(list13.isEmpty);//false      是否为空
 print(list13.isNotEmpty);//true     是否不为空
 print(list13.reversed);//(ccc, bbb, aaa)      返回一个List的倒序排列的Iterable  不改变原List
 print(list13.first);//aaa    第一个元素
 print(list13.last);//ccc    最后一个元素

set

在 Dart 中 Set 是一个元素唯一且无需的集合。

// set
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
// 要创建一个空集
var names = <String>{};
// 这样会创建一个 Map ,而不是 Set 。
// var names = {}; 
 // 这样也是可以的。
Set<String> names = {};

Map

这里的map,与js中的map完全不一样

Map 是用来关联 keys 和 values 的对象。 keys 和 values 可以是任何类型的对象。

不指定泛型

var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};
// 使用 Map 构造函数创建:
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings'; 

指定泛型

var map333 = <String,String>{};
map333["c"] ="c";
Map<int,String> map4 = new Map();
map4[1] = "a";
map4[2] = "b";

Rune

在 Dart 中, Rune 用来表示字符串中的 UTF-32 编码字符。

Symbol

一个 Symbol 对象表示 Dart 程序中声明的运算符或者标识符

主要运用:按名称引用标识符的 API

// 通过字面量 Symbol ,也就是标识符前面添加一个 # 号,来获取标识符的 Symbol 。
#radix
#bar

函数

普通函数

定义函数

// 返回值类型  方法名(参数){}
// 函数无返回值
// 类型用void 声明
// 返回值默认为null
void main(args) {
  ...
}

函数传参

// 函数有返回值,类型为 int
// 返回值默认为null
int sumValue(int a,int b) {
  int sum = a + b;
  print("a+b的和为:$sum"); 
  return sum;
}

函数传参(可选参数)

void printCouties(String name1,String name2,[String name3]) {
  print("文明国家有:$name1");
  print("文明国家有:$name2");
  if(name3 == null){
     print('name3不存在');
  }else{
    print("文明国家有:$name3");
  }
}

printCouties('中国','法国','德国');
printCouties('中国','法国');

函数参数 命名 赋默认值

void findVolume(int width,int lenth, {int height = 20}) {
  print("width:$width m");
  print("lenth:$lenth m");
  print("height:$height m");
}
main() 函数

任何应用都必须有一个顶级 main() 函数,作为应用服务的入口。如项目中所调用的那样!

箭头函数

箭头函数无返回值

sumValue(int a, int b)=>print(a + b);

箭头函数有返回值

int sumValue(int a, int b)=>a + b;
匿名函数
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});
函数是一等对象

一个函数可以作为另一个函数的参数。 例如:

void printElement(int element) {
  print(element);
}
var list = [1, 2, 3];
// 将 printElement 函数作为参数传递。
list.forEach(printElement);

dart高级语法

顾名思义,是一种具有相同属性(方法)的对象

// 定义类
class Student{
  int id; //  int id=10; 默认值
  String name; // String name="Mr wu";
  int age;
  void study(){
    print("${this.id}${this.name} 学习了");
  }
 }

void main() {
    // 实例化
  var student1 = Student();
  student1.id = 10;
  student1.name = "Mr wu";
  student1.study();
}

构造函数

以上调用比较繁琐,可以用在类中添加构造函数简化

构造函数,只要对象被实例化,就会自动执行

class Student{ 
 ...
  // 添加构造函数
  Student(int id,String name){
    this.id = id;
    this.name =name;
  }
  // 可简化为
  Student(this.id,this.name); 
 }
 // 实例化
var student1 = Student(1,'luy');
var student2= Student(2,'monica');

自定义构造函数

Student.myCustomConstructor(this.id, this.name,this.age);
// 自定义构造函数,需要用类去调用实现实例化
var student3=Student.myCustomConstructor(3,'momo',30);
print("${student3.name} + ${student3.age}");

类的继承

类的继承是很多语法常有的功能,dart同样也有这个

类与类之间也有相同的属性;

class Dog{
  String color;
  String name;
  void bark() {
    print("bark");
  }
  void eat() {
     print("eat");
  }
}
class Cat{
  String color;
  int age;
  void meow() {
    print("meow");
  }
  void eat() {
    print("eat");
  }
}

比如dog和cat,都有颜色,都会吃,属性和动作都是动物拥有的属性,

于是有一个公共的类(animal),让dog和cat直接继承animal的属性和方法即可;

class Animal {
  String color;
  void eat() {
    print("eat");
  }
}

我们通常将这种公共的类称其为父类;

extend继承Animal,保留其自身特色的特性

class Dog extends Animal{
  String name;
  void bark() {
    print("bark");
  }
}
class Cat extends Animal{
  void meow() {
    print("meow");
  }
}

重写父类方法和属性

class Dog extends Animal{
  void eat() {
    print("Dog eat");
  }
 }

当类和父类都有相同的方法名时,代码执行时,自动执行类中的自己的方法

类的Getters和Setter

也称计算属性,Getters和Setter(也称为访问器和更改器)允许程序分别初始化和检索类字段的值。

主要用在属性之间有联动变化。比如长方形中的长,宽,面积,长和宽任意一个变化,面积就会变化。

直接用计算属性:get area {return this.height * this.width;}

class Rect {
  num height;
  num width;
  Rect(this.height, this.width);
  // get 方法
  get area {
    return this.height * this.width;
  }

  // set 方法
  set areaHeight(value) {
    this.height = value;
  }
  // set 方法
  set areaWidth(value) {
    this.width = value;
  }
}
void main() {
  Rect r = new Rect(10, 4);
  print(r.area);
  //调用set方法
  r.areaHeight = 6;
  r.areaWidth = 5;
  //直接通过访问属性的方式访问area
  print("面积:${r.area}");
}

异常捕捉

和大多数语法一样,采用try {} catch{}

 void depositMoney(int amount){
    if(amount<0){
      throw Error;
    }
  }
  try {
   depositMoney(-1);
  } catch(e){
    print("err is $e");
  }

dart有一个类 Exception 封装好了异常处理

 try {
   depositMoney(-1);
  } catch(e){
    print(e.errorMessage());
  }
// 实现异常的方法
class DepositException implements Exception{
  String errorMessage(){
    return "金额不能少于0元";
  }
}

API

类型之间的转化

注意:强类型不支持隐式转化

any->string

dynamic age = 2;
age = '$age';

int -> string

age.toString();

string -> int

int.parse('100');

String -> double

var onePointOne = double.parse('1.1');

double->String

String piStr = 3.141592.toStringAsFixed(3); //结果为3.141

其他

    double figureB = 64.742;
    // 返回figureB的整数值
    print(figureB.toInt());
    // 返回figureB的双精度值
    print(figureB.toDouble());
    // 返回大于figureB的双精度值
    print(figureB.ceilToDouble());
    // 返回小于figureB的双精度值
    print(figureB.floorToDouble());
    // 返回figureB四舍五入的双精度值
    print(figureB.roundToDouble());
    // 返回figureB保留几位小数的字符串
    print(figureB.toStringAsFixed(2));
    // 返回figureB保留几位小数后精确结果的字符串
    print(figureB.toStringAsPrecision(3));

数据类型的API

int
    int figureC = 31;
    // figureC对比其他整数,0:相同、1:大于、-1:小于
    print(figureC.compareTo(20));
    // 将figureC控制在指定区间的整数
    print(figureC.clamp(20, 25));
    // 返回figureC转换成指定基数(进制)的字符串
    print(figureC.toRadixString(16));

    int figureD = 12;
    // 返回figureD与其他整数的最大公约数
    print(figureD.gcd(18));
    // 返回figureDg与其他整数的截取余数
    print(figureD.remainder(18));
    // 返回figureD几次幂值的字符串
    print(figureD.toStringAsExponential(2));
字符串

dart特有:三个单引号或三个双引号,

// 使用三个单引号或三个双引号 创建多行字符串,保留内在格式,如换行和缩进等,里面写什么输出就是什么。
    String e = '''asd
     fdsd
       fff
    
    ''';

字符串常用属性

    String a20 = "aaaa";
    String a21 = "";
    print(a20.length);//4  字符串长度
    print(a20.isEmpty);//false    是否为空
    print(a20.isNotEmpty);//true   是否不为空
    print(a21.isEmpty);//true
    print(a21.isNotEmpty);//false

字符串连接

    String a = "abcdefg";
    String b = '12345';
    String c = a + b; //使用+号连接
    String d = 'aaa' 'bbb'; //使用相邻空格符号连接,必须是两个字符串  不能是变量
    print(c); //abcdefg12345
    print(d); //aaabbb

字符串模板

使用${} 将一个字符串变量嵌入到另一个字符串内

    String a1 = "aa";
    String b1 = "bb${a1}bb";
    print(b1); //bbaabb
    String b2 = "bb${a1.toUpperCase()}bb";
    print(b2); //bbAAbb

字符串切割

    String a2 = "aaabbb";
    print(a2.substring(0, 2)); //aa   含头不含尾
    print(a2.substring(3)); //bbb  从指定index至末尾
    String a5 = "a,d,d  d,c,,";
    List<String> a6 = a5.split(",");//使用,分割,返回的是一个数组
    print(a6.length); //6
    print(a6); //[a, d, d  d, c, , ]

    String a8 = "a b,c";
    String a7 = a8.splitMapJoin(",",//查询“,”,用onMatch的返回值替换“,”用onNonMatch的返回值替换其他
        onMatch: (Match match) {
          return "a";
        }, onNonMatch: (String nonMatch) {
          return "b";
        });
    print(a7);//bab    a b,c  =>   bab

**字符串判断 **

是否包含或以xxx开始结束等

    String a3 = "aaabbbccc";
    print(a3.startsWith("aa")); //true
    print(a3.startsWith("aa", 3)); //false  从index=3开始判断
    print(a3.endsWith("c")); //true
    print(a3.contains("ab")); //true
    print(a3.contains("ac")); //false
    print(a3.contains("ab", 3)); //false  从index=3开始判断

字符串替换

    String a4 = "abcdeab";
    print(a4.replaceAll("ab","cc"));//cccdecc  替换全部符合条件的
    print(a4.replaceFirst("ab", "dd"));//ddcdeab  只替换第一个符合条件的
    print(a4.replaceFirst("ab", "dd",3));//abcdedd  从index=3开始  替换第一个
符合条件的
    print(a4.replaceRange(1, 3, "z"));// 范围替换 从0-3  含0不含3
    print(a4.replaceAllMapped("c", (Match match){//abyydeab  用方法返回值
替换指定的字符串
      return "yy";
    }));
    print(a4.replaceFirstMapped("b", (Match match){//abcdea333  从index=2开始 用方法返回值替换指定的字符串
      return "333";
    },2));

字符串查找

    String a9 = "aababcc1bc23";
    print(a9.indexOf("ab"));//1  第一个符合条件的index
    print(a9.indexOf("ab",2));//3   从index=2开始往后找
    print(a9.indexOf("ab",4));//-1   从index=4开始往后找,找不到返回-1
    print(a9.lastIndexOf("bc"));//8  从后往前找   返回第一个符合条件的index
    print(a9.lastIndexOf("bc",3));//-1  从后往前找  从index=3开始找  返回第一个符合条件的index  找不到返回-1
    print(a9.lastIndexOf("bc",7));//4  从后往前找  从index=7开始找  返回第一个符合条件的index

转换为大小写

    String a10 = "aaBBCc";
    print(a10.toLowerCase());//aabbcc
    print(a10.toUpperCase());//AABBCC

去除空格

    String a11 = "  aab  bcc  ";
    print(a11);//   aab  bcc
    print(a11.trim());//aab  bcc    去除左右两边空格
    print(a11.trimRight());//   aab  bcc   去除右边空格
    print(a11.trimLeft());// aab  bcc   //去除左边空格

补齐长度 剩余位使用指定字符串替换

    String a13 = "111";
    print(a13.padLeft(6));//   111     剩余3个位  默认使用""补齐
    print(a13.padRight(6,"c"));  //111ccc    剩余3个位   指定使用"c"
    print(a13.padRight(6,"dd"));  //111dddddd  剩余3个位   每个位指定使用"dd"   替换后总长度不是6
    print(a13.padLeft(2,"e"));//111    如果指定长度小于原字符串长度   返回原字符串

字符串先后比较

    String a12 = "bbcc";
    print(a12.compareTo("aaa"));//1   在ascii码中 b>a
    print(a12.compareTo("bbcc"));//0
    print(a12.compareTo("dd"));//-1    在ascii码中 b<d
List
List ListFollow = [1,2,3];
ListFollow.add(9);
list5[1] = 4;

大致简单介绍有以下方法可用,具体参考

addAll() 两个List合并

insert(index,element) 在指定index处插入值

insertAll(index,list) 在指定index处插入list 其余顺延

followedBy(list) 将自身和参数内list合成一个List

remove(item) 删除具体的元素 removeAt(index) 删除索引位置元素

emoveLast()删除末尾元素 removeRange(start,end) 范围删除 removeWhere() 根据条件删除

clear() 清空数组

修改指定index位置的值

setRange(startIndex,endIndex,list) 范围修改List的值

replaceRange(start,end,list)范围替换 含头不含尾

fillRange(start,end,value) 从start-end 每个元素用value替换

retainWhere(()=>(bool)) 根据条件筛选元素

setAll(index,list) 从index开始,使用list内的元素逐个替换本list中的元素

查看index位置的值

indexOf(element,[start]) 查找指定元素在list中的索引

any((element)=>(bool)) 判断List中是否有任意一个元素符合给定的参数

every((element)=>(bool)) 判断List中是否每个元素都符合参数函数

contains(obj) List中是否存在给定的obj

firstWhere((element)=>(bool)) 返回第一个满足条件的元素(不是元素的index)

遍历

ListFollow.forEach((item) {
 print(item);
});
Map

注意:这里的map,与js中的map完全不一样

新增/修改一个key-value

Map<String,int> map7 = {"a":1,"b":2,"c":3,"d":4,"e":5};
// 新增一个key value
map7["f"] = 6;
// 修改一个key的value
map7["a"] = 11;
// update() 对指定的key的value做出修改
int result3 = map7.update("c", (value)=>(value*2));
print(result3); // 6

updateAll() 根据参数函数的规则,批量修改map

 Map<String,int> map24 = {"a":1,"b":2,"c":3};
 map24.updateAll((String key,int value){
    return value*2;
 });
 print(map24);//{a: 2, b: 4, c: 6}

remove() 删除一个key

map24.remove("c");

removeWhere() 根据条件批量删除

map7.removeWhere((key,value)=>(value>3));

containsKey() 是否包含key

print(map7.containsKey("d"));

containsValue() 是否包含value值,同上

forEach() 遍历

 Map<String,int> map12 = {"a":1,"b":2,"c":3,"d":4,"e":5}; 
map12.forEach((String key,int value){
  print("$key  $value");
}

clear() 清空map

addAll() 整体合并另一个map 泛型要一致

map12.addAll(map7) 

dart特有:合并map并去重

addEntries() 合并两个map 如果key有重复,被合并的map的value覆盖前者

 Map<String,int> map26 = {"a":1,"b":2,"c":3};
 Map<String,int> map27 = {"a":1,"b":4,"d":3,"e":5};
 map26.addEntries(map27.entries);

给属性补数据

putIfAbsent() 存在key就获取值,不存在则添加到map ,返回值为属性值

Map<String,int> map18 = {"a":1,"b":2,"c":3};
int result = map18.putIfAbsent("a", ()=>(2));//存在   返回值1
int result2 = map18.putIfAbsent("d", ()=>(2));//不存在  返回值2