Dart

200 阅读6分钟

基础语法

main(){
    print('打印内容');
}
void main(){
//使用void没有返回值,表示main方法没有返回值
    print('你好dart');
}
//ts中方法定义没有返回值的方法
function setData:void(){
}

注释方法

ctrl+/或//或///

Dart的变量和常量

Dart的变量--String;int(数字) ;

dart是一个脚本类语言,可以不预先定义变量类型,会自动类型推倒--(类似Js)

var str='this is str';
var str = 123;
//或者直接写类型
String str = 'this is var';//字符串类型
int str = 123;//数字类型

注意:写了var就不要写类型,写了类型就不要写var;使用var推断类型之后就不要赋予其他类型值,并且Dart里有类型校验。

//报错
var String str = "this is str";
//报错
var str = "已推断为字符串类型";
str = 123;
//报错
String = 123;

Dart的命名规则

变量名称必须由数字、字母、下划线和美元符($)组成。
注意:标识符开头不能是数字
标识符不能是保留字和关键字。
变量的名字是区分大小写的如:age和Age是不同的变量。再实际运用中,建议不要用一个
标识符(变量名称)一定要见名思意 : 变量名称建议用名词,方法名称建议用动词。
//错误的表达方式👇
var 2str = 'xxx';
var if = 'xxx';

Dart的常量--const和final 修饰符

const值不变,一开始就得赋值

final可以开始不赋值,只能赋值一次;而final不仅有const的编译时常量的特性,最重要的是它是运行时常量,并且final是惰性初始化,既在运行时第一次使用前才初始化。

永不改变的量,请使用final或者const修饰它,而不是使用var或其他变量类型。

final的写法
1.
final PI = 3.14159;
print(PI);

2.
final a =new DateTime.now();
print(a);//打印结果为当前时间  例:2022-07-05-17:17:19.715306

Dart的数据类型

常用数据类型:
Numbers(数值):
    int
    double
Strings(字符串)
    String
Booleans(布尔)
    bool
List(数组/集合)
    在Dart中,数组是列表对象,所以大多数人只是称它们为列表
Maps(字典)
    通常来说,Map是一个键值对相关的对象。键和值可以是任何类型的对象。
不常用类型
Runes
Symbols

numbers类型

int 整数 double 小数(既可以是整型也可以是浮点,输出整型会带个小数位置,例:13.0)

运算符与其他语言一样 + - * / %

String类型写法

String str1 ='''  这样可以多行
第二行

第四行 最后记得加分号然后print输出
''';

String str1='单引号和双引号只能一行'

字符串的拼接

String str1 = '你好';
String str2 = 'Dart';
print("$str1 $str2")//输出结果 你好Dart
//第二种拼接方法
print(str1+str2) //输出结果 你好Dart
print(str1+" "+str2) //输出结果 你好 Dart

bool类型

true/false

bool flag=true;

List数组/集合

默认写法

var li = ["张三",20,true];

指定类型写法

var 12=<String>["张三","1"];

//定义空集合
var l4=[];

操作集合的方法

注意:

1.使用List.filled(,"")创建的集合长度是固定的, 不能再使用add方法

main(){
var abc=["1","2","3"];

//1.length查看长度
print(abc.length);

//2.添加内容add
abc.add("张三");//1 2 3 张三

//3.创建一个固定长度的集合List.filled
var bcd=List.filled(2,"") // 输出结果  [ , ]
本方法有类型推导,若不规定类型则自动推断
例
var bc=List<String>.filled(2,"");//推断为字符串类型,就不能赋予数字
bc[0]=222; //数字和规定的类型不同,会报错就会报错

//4.通过下标修改集合内容
bcd[0]="张三";
bcd[1]="李四"; //输出结果变为 [张三,李四]
}

//5.通过length修改长度
Liat a1 = ['a','b','c']; //打印结果 [a,b,c]
a1.length="4"; //打印结果[a,b,c,null]

Maps

定义Maps的方式

第一种定义 Maps的方式
var person={
    "key":"value" //在这里的key必须加引号,value根据需要类型定义 都可
    
    "name":"张三",
    "age": 20,
    "bool":true,
    "List":["张三","李四","王五"]
};

如果需要访问maps的内容,与js的person.name不同, 用person["name"]访问,例:
print(person.["name"])

第二种定义Maps的方式
var p=new Map();
p["name"]="李四";
p["age"]=22;
p["work"]=["程序员","送外卖"];
print(p);//输出结果{name:李四,age:22,work:[程序员,送外卖]}

Dart判断数据类型

通过is关键词来判断类型

main() {
  var str = 123.2;

  if (str is String) {
    print('是String类型');
  } else if (str is int) {
    print('int');
  } else {
    print('其他类型');
  }
}

Dart 运算符 条件表达式/判断 类型转换

1.Dart运算符

算术运算符
 +  -  *  /  ~/(取整)  %(取余)
关系运算符----返回bool值
 ==  !=  >  <  >=  <=
逻辑运算符
 !  &&  ||
赋值运算符
    基础赋值运算符 =  ??=
        ??= 表示 如果这个变量为空则赋值,不为空则不赋值例:
            var b = 10;
            b??=23;
            print(b); //打印10   因为b的值不为空
    复合赋值运算符 +=  -=  *=  /=  %=  ~/=
条件表达式
    if  else  switch case

Switch case判断固定值效率比较高

void main() {
  var sex = "男男";
  //使用switch case判断性别
  switch (sex) {
    case "男":
      print('性别是男');
      break;
    case "女":
      print("性别是女");
      print('可以输出多行');
      break;
    default:
      print('传入参数错误');
      break;
  }
}

三目运算符

main() {
  bool flag = true;
  String c = flag?"我是true":"我是false";
  print(c);
}

??运算符

main() {
  // ??运算符
  var a;
  var b = a ?? 10;
  print(b); //打印10 ,因为a为null
  /////////////////////////////////////////////////////
  var c = 22;
  var d = c ?? 10;
  print(d); //打印22 , 因为c有值
}

类型转换

1.Number与String类型之间的转换

Number类型转换成String类型 toString()

main(){
  //转换成String类型
  var myNum=12;
  var str=myNum.toString();
  print(str is String);//转换成功!输出true
}

String类型转换成Number类型 int.parse() --- double.parse()

main() {
  String str = '123.9';
  var numbers = double.parse(str); //int.parse和double.parse都可以用
  print(numbers is double); //打印true  转换成功!
}

parse类型转换失败处理方法-----try ... catch

main() {
  //try catch方法 --处理类型转换失败防崩溃方法
  String price = ''; //获取到的数据为空,无法进行double或int类型转换,
  try {
    //使用此方法,若报错则执行打印0
    var myNum = double.parse(price);
    print(myNum);
  } catch (err) {
    //这里的err参数好像随便更改,并不确定
    print(0); //报错打印0
  }
}

2.其他类型转换成Booleans类型

isEmpty:判断字符串是否为空

main() {
  //通过isEmpty判断字符串是否为空
  var str = '';
  if (str.isEmpty) {
    print('str空');//输出为空
  }else{
    print('str不为空');
  }
}

isNaN:判断值是否为NAN

main() {
  //判断值是否是NaN
  var myNum = 0 / 0; //0除以0等于nan
  if (myNum.isNaN) {
    print('Nan');
  }
}

Dart中的循环 for ; while ; do..while;

for循环

main() {
  for (int a = 1; a <= 10; a++) {
    print(a); //打印1-10 循环10次
  }
}

打印二位数组中指定的值

main() {
  //打印二维数组中指定的值
  List list = [
    {
      "care": "国内",
      "news": [
        {
          "title": "国内新闻1",
          "title1": '12345',
        },
        {"title": "国内新闻2"},
        {"title": "国内新闻3"},
      ]
    },
    {
      "care": "国外",
      "news": [
        {"title": "国外新闻1"},
        {"title": "国外新闻2"},
        {"title": "国外新闻3"},
      ]
    },
  ];
  print(list[0]["news"][0]["title1"]); //打印结果12345
}

while循环--要注意结束条件不能死循环

main() {
  int i = 1;
  while (i <= 10) {
    print(i);
    i++;
  }
}

do while 循环 --和while的区别在于do是先执行再判断 , while先判断再执行

main() {
  int i = 20;
  do{
    print('先执行一次');
  }while(i<10);
}

break语句的功能

1.在switch语句中使流程跳出跳出switch结构。

2.在循环语句中使流程跳出当前循环,遇到break 循环终止,后面代码也不会执行

main() {
  for(var i=1;i<=6;i++){
    if(i==4){
      break;//跳过i==4之后的循环,循环结束
    }
    print(i);//输出 1 2 3
  }
}

强调

1.如果在循环中已执行break语句,就不会执行循环体中位于break后的语句。

2.在多层循环中,一个break只能向外跳出一层

break可以在switch--case中,也可以在for循环和while循环中

continue语句的功能

[注]只能在循环语句中使用,使本次循环结束,既跳过循环体重在下面尚未执行的语句,接着进行下面的语句

continue可以在for循环以及while循环中,但是不建议用在while循环中,不小心容易死循环

main() {
  for(var i=1;i<=6;i++){
    if(i==4){
      continue;//跳过i==4时的循环
    }
    print(i);//输出 1 2 3 5 6
  }
}

Dart集合类型以及循环语句

集合类型List;Set;Map

List

常用属性:
  length      长度
  reversed    翻转
  isEmpty     是否为空
  isNotEmpty  是否不为空
常用方法:
  add         增加一个
  addAll      拼接数组
  indexOf     查找  传入具体值
  remove      删除  传入具体值
  removeAt    删除  传入索引值
  filled      创建固定长度的数组
  fillRange   修改
  insert(index,value);      指定位置插入
  insertAll(index,list)     指定位置插入List
  toList()    其他类型转换成List
  join()      List转换成字符串
  split()     字符串转换成List
  forEach
  map
  where
  any
  every

length;isEmpty;isNotEmpty;reversed

注: reversed翻转的只是数据,想翻转成数组需要搭配toList使用

main() {
  List myList = ['香蕉', '牛奶'];
  print(myList.length); //打印2---长度为2
  print(myList.isEmpty); //打印false--判断是否为空----不为空
  print(myList.isNotEmpty); //发音true--判断是否不为空---不为空
  print(myList.reversed);//打印(牛奶,香蕉)--翻转myList
}

add增加

main() {
  List a1 = ['草莓', '西瓜', '苹果'];
  print(a1.length); //长度为3,数据为草莓,西瓜,苹果
  a1.add('牛奶');
  print(a1.length); //长度为4,数据为草莓,西瓜,苹果,牛奶
}

addAll拼接数组

main() {
  List myList = ['香蕉', '牛奶'];
  myList.addAll(['鸡蛋','蛋鸡']);
  print(myList);//打印[香蕉,牛奶,鸡蛋,蛋鸡]--将两个数组拼接在一起
}

indexOf查找索引值(下标)

main() {
  List myList = ['香蕉', '牛奶', '傀儡', '怪兽'];
  print(myList.indexOf('飞碟')); //查找不到返回-1
  print(myList.indexOf('牛奶')); //返回索引值1
  print(myList.indexOf('傀儡')); //返回索引值2(下标)
}

remove删除数据

main() {
  List myList = ['香蕉', '牛奶', '傀儡', '怪兽'];
  myList.remove('香蕉');//删除'香蕉'
  print(myList);//打印[牛奶,傀儡,怪兽]
}

removeAt删除下标对应的数据

main() {
  List myList = ['香蕉', '牛奶', '傀儡', '怪兽'];
  myList.removeAt(0);//删除下标为0的数据
  print(myList);//打印[牛奶,傀儡,怪兽]
}

filled创建固定长度list

main() {
  // var lst = List.filled(length, fill) ----length是长度,fill是内容,一般为空''
  //var lst = List<String>.filled(2, '',);-----可以在List后指定类型
  var lst = List.filled(2, '',);
  print(lst);//打印[ , ]
}

fillRange修改

main() {
  List myList = ['香蕉', '牛奶', '傀儡', '怪兽'];
  //myList.fillRange(start, end)-----start开始位置;end结束位置,然后设置数据
  //myList.fillRange(1, 3,);//1代表0-1之间;3代表2-3之间
  //myList.fillRange(1, 3,);//不设置值就为null--输出[香蕉,null,null,怪兽]
  myList.fillRange(1, 2, 'aaa'); //打印[香蕉,aaa,傀儡,怪兽]
  print(myList); //打印[牛奶,傀儡,怪兽]
}

insert插入一个

main() {
  List myList = ['香蕉', '牛奶',];
  myList.insert(1,'aaa');//在0-1之间插入aaa
  print(myList);//打印[香蕉,aaa,牛奶]
}

insertAll插入多个

main() {
  List myList = ['香蕉','牛奶',];
  myList.insertAll(1, ['aaa', 'bbb']); //在0-1之间插入aaa
  print(myList); //打印[香蕉,aaa,bbb,牛奶]
}

toList

main() {
  List myList = ['香蕉', '牛奶'];
  //print(myList.reversed);------打印(牛奶,香蕉)--翻转myList
  print(myList.reversed.toList()); //打印[牛奶,香蕉]---这个数据才是List
  
  //第二种分开写法:
  List myList = ['香蕉', '牛奶'];
  var newMyList = myList.reversed;
  var lowMyList = newMyList.toList();
  print(lowMyList);//打印[牛奶,香蕉]
}

join转字符串

main() {
  List myList = ['香蕉','牛奶',];
  var sty = myList.join('-');//以'-'为间隔转换成字符串返回新变量
  print(sty);//打印香蕉-牛奶
}

split 字符串转List

main() {
  var str = "香蕉-牛奶-西瓜";
  //var list=str.split(pattern)--pattern表示作为分割的符号
  var list=str.split('-');
  print(list);//打印[香蕉,牛奶,西瓜]
}

map 群体操作

将myList的数据全部*2

main() {
  List myList = [1, 3, 4];

  var newList = myList.map((value) {
    return value * 2;//将myList中的数据*2
  });
 
  print(newList.toList());//打印[2,6,8]
}

where 筛选符合条件的内容组成新数组

main() {
  List myList = [1, 3, 4];
  var newList = myList.where((value) {
    return value > 3;
  });
  print(newList.toList());//打印[4]
}

any 判断是否符合条件

main() {
  List myList = [1, 3, 4];
  var f = myList.any((value) {
    return value > 3; //只要集合里有满足条件的就返回true
  });
  print(f); //打印true
}

every 集合内每个都满足条件才返回true

main() {
  List myList = [1, 3, 4];
  var f = myList.every((value) {
    return value > 3; //集合里每一个都满足条件的才返回true
  });
  print(f); //打印false
}

循环语句forEach;map;where;any;every

Set

Set是没有顺序且不能重复的集合,所以不能通过索引去获取值

 main() {
  var s = new Set(); //定义一个Set集合
  //var s= new List()---如果是List则会打印出[香蕉,苹果,苹果]
  s.add('香蕉');
  s.add('苹果');
  s.add('苹果');
  print(s); //打印{香蕉,苹果}
}

通过Set进行去重

main() {
  List Mylist = ['苹果', '香蕉', '苹果', '香蕉', '苹果'];
  var s = new Set(); //定义一个Set集合
  s.addAll(Mylist);//将Mylist数组的数据添加到Set集合中
  print(s);//打印{苹果,香蕉}--已经去重
  print(s.toList());//打印[苹果,香蕉]--将已经去重的方法通过toList()方法转换成数组
}

映射(Maps)

映射(Maps)是无序键值对

常用属性:
  keys          获取所有的key值
  values        获取所有的value值
  isEmpty       是否为空
  isNotEmpty    是否不为空
常用方法:
  remove(key)   删除指定key的数据
  addAll({...}) 合并映射  给映射内增加属性
  containsValue 查看映射内的值  返回true/false
  forEach
  map
  where
  any
  every

定义maps的方法1

main() {
  var person = {
    "name": "张三", 
    "age": 20
    };
    print(person);//打印{name:张三,age:20}
}

定义maps的方法2

main() {
  var m=new Map();
    m["name"]="李四";
    print(m);//打印{name:李四}
}

keys;values

main() {
  var m = new Map();
  m["name"] = "李四";
  m["age"] = 20;
  print(m.keys); //打印(name,age)
  print(m.values); //(李四,20)
  //想要获取到数据需要转成数组,使用.toList()
  print(m.keys.toList());//打印[name,age]
}

isEmpty是否为空;isNotEmpty与list使用方法一致

常用方法: remove(key)

main() {
  var m = {"name": '张三', "age": 20};
  m.remove("age");//将age删除
  print(m);//打印{name:张三}
}

addAll

main() {
  var m = {"name": '张三', "age": 20};
  m.addAll({//----------------------添加到m里
    "work": ['敲代码', '送外卖'],
    "height": 160
  });
  print(m);
}

containsValue 查看映射内的值 返回true/false

main() {
  var m = {"name": '张三', "age": 20};
  print(m.containsValue('张三')); //打印true
  print(m.containsValue('李四')); //打印false---因为values没有李四
}

遍历List的方法

方法1

main() {
  List myList = ['香蕉', '苹果', '西瓜'];

  for (var i = 0; i < myList.length; i++) {
    print(myList[i]);
  }
}

方法2

main() {
  List myList = ['香蕉', '苹果', '西瓜'];

  for(var item in myList){
    print(item);
  }
}

方法3---------forEach方法---list

main() {
  List myList = ['香蕉', '苹果', '西瓜'];

  myList.forEach((value) {
    print("$value");
  });
}

forEach方法操作Set

main() {
  //set
  var s = new Set();

  s.addAll([1, 222, 333]);

  s.forEach((value) => print(value)); //打印11 222 333   (这是单行代码写法)
}

forEach方法操作map

main() {
  //Map
  Map person = {"name": "张三", "age": 20};

  person.forEach(
    (key, value) {
      print("$key--$value"); //打印name--张三  age--20
    },
  );
}

Dart中的函数 函数的定义 可选参数 默认参数 命名参数 箭头函数 匿名函数 闭包等

自定义方法:

自定义方法的基本格式:

注意: 定义的方法有作用域,在外面定义的是全局作用域,在局部定义的是局部作用域,

返回类型 方法名称(参数1,参数2,...){
    方法体
    return 返回值;
}

可选参数方法定义

//定义一个可选参数的方法
//int后面为什么加一个?
//原因:这是由于 Flutter SDK 版本升级, 对语法的检查变得更加严格,在编译过程中对构造方法中的类添加了空判断;在 Dart 类的成员变量定义时,在类型后面添加 ? 符号,将其声明为可空类型,与 Kotlin 类似,修改后,编译不再报错;
String printUserInfo(String username, [int? age]) {
  if (age != null) {
    return "姓名:$username---年龄:$age";
  }
  return "姓名:$username----年龄:保密";
}
main() {
  print(printUserInfo("张三")); //姓名:张三----年龄:保密
  print(printUserInfo("张三", 21)); //姓名:张三---年龄:21
}

默认参数定义方法

//定义一个可选参数的方法
//int后面为什么加一个?
//原因:这是由于 Flutter SDK 版本升级, 对语法的检查变得更加严格,在编译过程中对构造方法中的类添加了空判断;在 Dart 类的成员变量定义时,在类型后面添加 ? 符号,将其声明为可空类型,与 Kotlin 类似,修改后,编译不再报错;
String printUserInfo(String username, [int? age, String sex = '男']) {
  //形参
  if (age != null) {
    return "姓名:$username--性别:$sex--年龄:$age";
  }
  return "姓名:$username--性别:$sex--年龄:保密";
}

main() {
  print(printUserInfo("张三")); //姓名:张三--性别:男--年龄:保密
  print(printUserInfo("张三", 21)); //姓名:张三--性别:男--年龄:21
}

命名参数定义方法

//定义一个可选参数的方法
//int后面为什么加一个?
//原因:这是由于 Flutter SDK 版本升级, 对语法的检查变得更加严格,在编译过程中对构造方法中的类添加了空判断;在 Dart 类的成员变量定义时,在类型后面添加 ? 符号,将其声明为可空类型,与 Kotlin 类似,修改后,编译不再报错;
String printUserInfo(String username, {int? age, String sex = '男'}) {
  //形参
  if (age != null) {
    return "姓名:$username--性别:$sex--年龄:$age";
  }
  return "姓名:$username--性别:$sex--年龄:保密";
}

main() {
  print(printUserInfo("张三", age: 21, sex: '未知')); //姓名:张三--性别:未知--年龄:21
}

实现把一个方法当作参数

main() {
  fn1() {
    //fn1执行会打印111
    print("111");
  }

  fn2(fn) {//将fn1赋值给fn  然后执行fn===执行fn1 
    //fn2函数   形参fn
    fn();
  }

  fn2(fn1); //调用fn2函数  传入参数fn1
}

箭头函数---只能实现一句,不能实现多句

main() {
  //不使用箭头函数
  List list=['苹果','香蕉','西瓜'];
  list.forEach((value) {
    print(value);//打印苹果 香蕉 西瓜
  });
}


main() {
  //使用箭头函数
  List list = ['苹果', '香蕉', '西瓜'];
  list.forEach((value) => print(value)); //打印苹果 香蕉 西瓜}
}


main() {
  //使用箭头函数另一种方法
  List list = ['苹果', '香蕉', '西瓜'];
  list.forEach((value) => {
    print(value)//打印苹果,香蕉,西瓜
  });
}

修改下面List里面的数据,让数组中大于2的值乘以2

main() {
  List list = [4, 1, 2, 3, 4];

  var newList = list.map((value) {
    if (value > 2) {
      return value * 2;
    }
    return value;
  });
  print(newList.toList());
}

使用箭头函数修改下面List里面的数据,让数组中大于2的值乘以2

main() {
  List list = [4, 1, 2, 3, 4];
  var newList = list.map((value) => value > 2 ? value * 2 : value);
  print(newList.toList());
}

匿名方法

main() {
  //匿名方法 把方法赋值给一个变量
  var printNum = (n) {
    print(n + 2);
  };
  printNum(12); //打印14
}

自执行方法

main() {
  //自执行方法---自己会执行
  (() {
    print('我是自执行方法'); //打印 我是自执行方法
  })();
}

自执行方法2

main() {
  //自执行方法---自己会执行
  ((n) {
    print(n); //打印12
  })(12);
}

方法的递归---方法可以调用自己

main() {
  num sum = 1;
  fn(n) {
    sum *= n;
    if (n == 1) {
      return;
    }
    fn(n - 1);
  }

  fn(5);
  print(sum);
}

通过递归的方法求1-100的和

main() {
  //通过递归方法球1-100的和
  var sum = 0;
  fn(int n) {
    sum += n;
    if (n == 0) {
      return;
    }
    fn(n - 1);
  }

  fn(100);
  print(sum);
}

闭包

1.全局变量特点: 全局变量常驻内存、全局变量污染全局

2.局部变量的特点: 不常驻内存,会被垃圾机制回收、不会污染全局

想实现的功能:

1.常驻内存

2.不污染全局

产生了闭包,闭包可以解决这个问题.....

闭包:函数嵌套函数,内部函数会调用外部函数的变量或参数

闭包的写法: 函数嵌套函数,并return里面的函数,这样就形成了闭包

类 对象

面向对象编程(00P)的三个基本特征是:封装、继承、多态

Dart所有的东西都是对象,所有的对象都继承自0bject类。

Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是obiect的子类一个类通常由属性和方法组成。

自定义类

class Person {
  String name = "张三";
  int age = 23;

  void getInfo() {
    //void代表没有返回值
    //print("$name---$age");

    print("${this.name}---${this.age}");
  }
}

//在main()中使用这个类需要先进行实例化
void main() {
  //实例化
  var p1 = new Person(); //实例化之后将Person赋给p1

  print(p1.name);//打印张三

  p1.getInfo();//打印"${this.name}---${this.age}"  也就是打印  张三---23
}

类在实例化时可以标注类型

Person p2 = new Person();
  print(p2.name);//张三

给类中设置传参修改的方法

class Person {
  String name = "张三";
  int age = 23;

  void getInfo() {
    //void代表没有返回值
    //print("$name---$age");

    print("${this.name}---${this.age}");
  }

  void setInfo(int age) {  //记得要设置传参类型
    //设置age的方法
    this.age = age;
  }
}

//在main()中使用这个类需要先进行实例化
void main() {
  Person p2 = new Person();
  p2.setInfo(1111);
  print(p2.age);//类中原本定义为23  通过setInfo方法修改后 打印1111
}

默认构造函数--在实例化时默认触发

class Person {
  String name = "张三";
  int age = 23;
  //默认构造函数
  Person() {
    print('这是构造函数里的内容,这个方法在实例化时触发');
  }

  void getInfo() {
    //void代表没有返回值
    //print("$name---$age");

    print("${this.name}---${this.age}");
  }
}

//在main()中使用这个类需要先进行实例化
void main() {
  Person p2 = new Person();//进行实例化,触发默认构造函数
}

在实例化时动态指定属性

class Person {
  String name = ''; //这里需要定义初始化数据,赋值或使用late
  late int age;
  //默认构造函数
  Person(String names, int ages) {
    this.name = names;
    this.age = ages;
  }
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

void main() {
  Person p1 = new Person("张三", 20);
  p1.printInfo();
}

默认构造函数的简写

class Person {
  String name = ''; //这里需要定义初始化数据,赋值或使用late
  late int age;
  //默认构造函数
  Person(this.name, this.age); //简写
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

void main() {
  Person p1 = new Person("张三", 20);
  p1.printInfo();
}

命名构造函数

class Person {
  String name = ''; //这里需要定义初始化数据,赋值或使用late
  late int age;
  //默认构造函数
  Person(this.name, this.age);
  Person.now() {
    print('我是命名构造函数');
  }
  Person.setInfo(String name, int age) {
    this.name = name;
    this.age = age;
  }
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

void main() {
  Person p1 = new Person.now(); //我是命名构造函数
  Person p2 = new Person.setInfo("李四", 88);
  p2.printInfo(); //李四---88
}

自定义类要放在外置文件lib中,然后通过import '路径'引入即可

Dart中的私有方法

使用_把一个属性方法定义为私有---其他文件使用import访问不到,只有在当前文件中才可以使用该属性

class Animal {
  late String _name; //私有属性
  int age;
  //默认构造函数的简写
  Animal(this._name, this.age);

  void printInfo() {
    print("${this._name}----${this.age}");
  }
}

上述代码中,_name属性是私有属性,只有在该.dart文件内才可以访问到,在其他文件中调用无效会报错

如果想访问私有方法,可以使用公共方法的this进行间接调用

class Animal {
  String _name = '小猫'; //私有属性
  int age;
  //默认构造函数的简写
  Animal(this._name, this.age);

  void printInfo() {
    print("${this._name}----${this.age}");
  }

  void _run() {
    //定义一个私有方法
    print('这是一个私有方法');
  }

  execRun() {
    //这是一个公有方法,使用this看当前实例
    this._run(); //类里面方法的相互调用
  }
}

在另一个文件引用公共方法execRun来达到目的

import './index.dart';

main() {
  Animal a1 = new Animal('小狗', 1);
  // a1._run; //因为是私有方法 所以会报错
  a1.execRun();//通过公共方法间接调用私有方法
}

类中的getter 和setter修饰符的用法--用到了再找

Dart中的静态成员 静态方法

Dart中的静态成员:

1.使用static关键字来实现类级别的变量和函数

2.静态方法不能访问非静态成员,非静态方法可以访问静态成员

class Person {
  //通常来说,非静态属性和非静态方法通过new来访问,而使用static进行静态属性和静态方法之后,就可以直接访问。
  static String name = "张三"; //静态属性
  static void show() {
    //静态方法
    print(name);
  }
}

main() {
  // var p = new Person();----常规
  // p.show();----------------常规

  print(Person.name); //打印张三
  Person.show(); //打印张三
}

注:使用非静态方法访问静态成员时,不能使用this,因为this是当前类的实例,相当于new 这个实例,直接访问即可

class Person {
  static String name = "张三"; //静态属性
  int age = 20;
  static void show() {
    //静态方法
    print(name);
  }

  void printInfo() {
    //非静态方法
    print(name); //访问静态
    print(this.age); //访问非静态
  }
}

main() {
  Person aa1 = new Person();
  aa1.printInfo(); //张三 20
}

Dart中的对象操作符

? 条件运算符(了解)

as 类型转换

新版本不可以----需要注意
class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

main() {
  var p1 = '';
  p1 = new Person("张三", 22);
  // p1.printInfo();
  (p1 as Person).printInfo(); // 通过as将p1转成Person类型  老版本
}

is 类型判断

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

main() {
  Person p = new Person("张三", 20);
  if (p is Person) {
    //判断p是否属于Person类型
    p.name = "属于";
  }

  p.printInfo(); //属于---20
  print(p is Object); //true
}

.. 级联操作(连缀)

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

main() {
  Person p1 = new Person("张三", 22);
  p1.printInfo();

  // p1.name = "修改了";
  // p1.age = 44;
  // p1.printInfo(); //修改了---44
  //这样操作起来会有重复操作,所以可以使用..进行级联操作,更加简单

  p1
    ..name = "修改了"
    ..age = 44
    ..printInfo();//修改了---44
}

Dart中的类的继承

1.子类使用extends关键词来继承父类

2.子类会继承父类里面可见的属性和方法,但是不会继承构造函数

3.子类能复写父类的方法 getter和setter

class Person {
  String name = '张三';
  num age = 20;
  Person(this.name, this.age);
  Person.empty() {} //在Dart中,如果您的子类想要继承父类的构造函数,您需要确保父类有一个无参数的未命名构造函数,或者显式地在子类构造函数中调用父类构造函数。并且,需要给属性设置默认参数,对其进行初始化来保证继承。
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

class Web extends Person {
  //使用extends继承Person
  Web() : super.empty();
}

main() {
  Web w = new Web();
  print(w.name);
  w.printInfo();
}

覆写父类的方法

@override---- 表示下面的方法是覆写父类里的方法的---可以写也可以不写

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }

  work() {
    print("${this.name}在工作...");
  }
}

class Web extends Person {
  Web(super.name, super.age);
  run() {
    print('run');
  }

  //覆写父类的方法
  @override //表示下面的方法是覆写父类里的方法的---可以写也可以不写
  void printInfo() {
    print("姓名:${this.name}---年龄:${this.age}");
  }

  @override
  work() {
    print("${this.name}真的没有在工作...");
  }
}

main() {
  Web w = new Web('李四', 20);
  w.printInfo(); //姓名:李四---年龄:20
  w.work();//李四真的没有在工作...
}

自类调用父类的方法

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }

  work() {
    print("${this.name}在工作...");
  }
}

class Web extends Person {
  Web(super.name, super.age);
  run() {
    print('run');
    super.work(); //自类调用父类的方法
  }

  @override
  void printInfo() {
    print("姓名:${this.name}---年龄:${this.age}");
  }
}

main() {
  Web w = new Web('李四', 20);
  w.printInfo(); //姓名:李四---年龄:20
  w.run(); //  run  李四在工作...
}

Dart中的抽象类 多态 和接口

抽象类

Dart中的抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。

1.抽象类通过abstract关键字来定义

2.Dart中的抽象类方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。

3.如果子类继承抽象必须得实现里面的抽象方法

4.如果把抽象类当作接口实现的话必须得实现抽象类里面定义的所有属性和方法

5.抽象类不能被实例化,只有继承它的子类可以

extends抽象类和implements的区别:

1.如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类

2.如果只是把抽象类当作标准的话我们就用implents实现抽象类

案例1:定义一个Animal类要求它的子类必须包含eat方法

abstract class Animal {
  eat(); // 抽象方法1---子类必须实现父类的抽象方法,抽象类在main中不能被实例化,只能通过子类继承
}

class Dog extends Animal {
  @override
  eat() {
    print('小狗乖乖');
  }
}

main() {
  Dog a1 = new Dog();
  a1.eat();
}

多态

允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果

子类的实例赋值给父类的引用。

多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现

abstract class Animal {
  eat(); // 抽象方法1
  run();
}

class Dog extends Animal {
  @override
  eat() {
    print('小狗乖乖');
  }

  @override
  run() {
    print("run方法111");
  }
}

class Cat extends Animal {
  @override
  eat() {
    print('小猫跳跳');
  }

  @override
  run() {
    print("run方法222");
  }
}

main() {
  Dog a1 = new Dog();
  a1.eat();
  a1.run();
  Cat a2 = new Cat();
  a2.eat();
  a2.run();
}

接口

首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。

同样使用implements关键字进行实现。

但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。

而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像]ava接口那样的方式,一般会使用抽象类。

建议使用抽象类定义接口。

定义一个DB库 支持mysql mssql mongodb

mysql mssql mongodb三个类里面都有同样的方法

abstract class Db {
  //当作接口
  late String uri; //数据库的链接地址
  add(String data); //新增
  save(); //保存
  delete(); //删除
}

/////////////////////////////////////////////////////////////////////////
class Mysql implements Db {
  @override
  String uri;

  Mysql(this.uri);
  @override
  add(String data) {
    print('这是mysql的add方法' + data);
    // throw UnimplementedError();
  }

  @override
  delete() {
    // throw UnimplementedError();
  }

  @override
  save() {
    // throw UnimplementedError();
  }
}

/////////////////////////////////////////////////////////////////////////
class MsSql implements Db {
  @override
  String uri;
  MsSql(this.uri);
  @override
  add(data) {
    // throw UnimplementedError();
  }

  @override
  delete() {
    // throw UnimplementedError();
  }

  @override
  save() {
    // throw UnimplementedError();
  }
}

main() {
  Mysql mysql = new Mysql('xxxxxx');

  mysql.add('1321313');
}

dart中一个类实现多个接口

abstract class A {
  late String name;
  printA();
}

abstract class B {
  printB();
}

class C implements A, B {
  @override
  printA() {
    print('A方法');
  }

  @override
  late String name;

  @override
  printB() {
    print('B方法');
  }
}

main() {
  C c = new C();
  c.printA(); //A方法
  c.printB(); //B方法
}

dart中的mixins混入----with关键词

mixins的中文意思是混入,就是在类中混入其他功能。

在Dart中可以使用mixins实现类似多继承的功能

因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:

1、作为mixins的类只能继承自0bject,不能继承其他类

2、作为mixins的类不能有构造函数

3、一个类可以mixins多个mixins类

4、Amixins绝不是继承,也不是接口,而是一种全新的特性

Dart2.13后的新特性

P12 由于新特性 代码有问题---12---13--14都没看