Flutter 之 Dart基础 从零学

加粗样式

提示:此文章为前端学习flutter过程,如有歧义期望各位大大的宝贵意见

学习Dart 基础知识 移步这里
安装flutter环境相关 移步这里
flutter基础组件使用相关 移步这里

文章目录


前言

提示:想学好flutter需要先学号Dart;
·flutter 安装流程·


一、什么是Dart?

提示:以下是本篇文章正文内容,下面案例可供参考

1.了解Dart

Dart官方文档:链接地址
Dart For Windows:下载地址

2.安装Dart(windows)mac自行安装;

1.下载下载地址 傻瓜式,一步步安装,等待
在这里插入图片描述2.检查是否安装成功在‘cmd’ 中输入

dart  --version

安装成功
在这里插入图片描述

3.开发工具 vscode 插件安装

1.下载 vscode:下载地址
2.安装vscode软件
3.给vscode安装dart插件
在这里插入图片描述
在开发工具中选在左箭头,在上箭头输入 dart 和 code runner
在这里插入图片描述

4.运行我的第一个dart文件

文件命名需要有以.dart结束;例如:index.dart

main() {  // 入口文件 
  print('hello dart...');
}

二、Dart使用

1.声明返回值为空的入口文件

代码如下(示例):

void main() {  // void 代表返回值为空
  print('hello dart...');
}

2.Dart变量的声明及使用

1.使用var 定义的变量 可以自行推倒其类型;
2.使用 数据类型定义的变量不可推到,切只能为定义的类型;
代码如下(示例):

void main() {
  var str = 'zhangsan'; // 这里自动推倒str是字符串类型
  // str = 123  // 如果给str赋值其他数据类型的值,会出现报错
  print(str);

  String str2 = 'lisi'; // 定义字符串类型的变量
  // str2 = 10  // 如果给str2赋值其他数据类型的值(数字),会出现报错
  print(str2);
}

在这里插入图片描述

注意:如果变量类型确定了,再给变量赋值其他类型的值,会出现如上图的报错~


3.Dart命名规则

在这里插入图片描述

4.Dart 常量

在这里插入图片描述

 void main(){
	 // 这里只能用final    start
	 final a = new DateTime.now();
	  // const b = new DateTime.now(); // 错误写法,这里是能用final
	  print(a);
	 // 这里只能用final    end
	
	 // 这种方法使用final和const结果是一样的 start
	  final c = 3.14159;
	  const d = 3.14159; 
	  print(c);
	  print(d);
	 // 这种方法使用final和const结果是一样的 end
 }

注意:常量不可修改~

5.Dart 数据类型

在这里插入图片描述

5.1.定义字符串String和var及字符串换行效果

  var str1 = '这是一个字符串';
  String str2 = '这也是一个字符串';
  print(str1);
  print(str2);
  var str3 = '''
    这是一个换行
    这是一个换行
    这是一个换行
  ''';
  print(str3); // 字符串换行 单引号双引号都支持

注意:可以用String和var定义 ;‘’’ 字符串可识别到换行 ‘’’

5.2.定义数值类型int 和double

 int a = 22; 
  a = 43; // int定义的变量赋值必须是int,否则报错;
  print(a);

  double b = 34.33;
  b = 30; // double定义的变量赋值可以是int 也可以是double都支持赋值,整型会转化为30.0
  print(b);

注意:int定义的变量赋值必须是int,否则报错;double定义的变量赋值可以是int 也可以是double都支持赋值,整型会转化为30.0

5.3.定义布尔类型bool

  bool flag = true;
  var flay = true;
  print(flay);
  print(flag);
  if (flay == flag) {
    print('成功了');
  } else {
    print('失败了。。');
  }

5.4.定义List类型数值四种方式

   // 第一种定义List的方式 不指定类型
  var list = [1, 2, '颤三1']; // list中所有值可以为任何类型;var 可以换成List
  print(list);
  list.length = 0;
  print(list);

  // 第二种定义List的方式 指定类型
  var list2 = <String>['颤三2', '李四2', '王五2']; // 指定list中的所有值必须是字符串类型;var 可以换成List
  print(list2);

  // 第三种定义List的方式 增加数据,通过[]创建的集合变量他的容量是可以变的,就是可以改值;
  var list3 = []; // 不管这里有没有默认值,都是可以add增加的
  list3.add('张三3');
  list3.add('李四3');
  list3.add('王五3');
  print(list3);

  // 第四种定义List的方式
  // var lists4 = new List(); // 这种方法再最新版dart中作废了,新版不能再使用了,不建议使用;

  // 创建固定长度的集合,只能为定义的,不能增不能少;
  var lists5 = List.filled(2, '');  // var 可以换成List
  print(lists5);
  print(lists5.length);
  print('list5[0] = ' + lists5[0]);
  print('list5[1] = ' + lists5[1]);
  lists5[0] = '颤三5';
  lists5[1] = '李四5';
  print(lists5);
  print(lists5.length);
  // lists5.add('王五'); // 这里会报错,因为长度固定无法新增;
  // lists5.length = 0 ; // 这里会报错,因为长度固定无法减少;

  var list6 = List<String>.filled(3, ''); // 指定长度指定数组每个值的类型;var 可以换成List

注意:跟js中的array 一样;样例中的var 可以换成List 来定义变量;

5.5.List 常用属性和方法

1.常用属性
length 长度
reversed 翻转
isEmpty 是否为空
isNotEmpty 是否不为空

  List lists = [1, 10, 3, 6];
  print(lists.length);              //  结果4
  print(lists.reversed);            //  (6,3,10,1)
   print(lists.reversed.toList());  //  [6, 3, 10, 1]
  print(lists.isEmpty);             //  false
  print(lists.isNotEmpty);          //  true

2.常用方法

add(值) 添加数据 添加一个
addAll(数组) 拼接数组
indexOf(值) 查找数据返回值:成功返回数组下标,失败返回-1;
remove(值) 删除 传入具体值 返回值:true或false,表示删除成功或者失败;
removeAt(下标) 删除 传入索引值 返回值:删除的值
fillRange(开始下标,结束下标,'修改的值') 修改 传入开始和结束索引值必传 和 修改值
insert(下标,值) 插入 下标和值
insertAll(下标,数组) 插入 下标和数组
join('-') 和split('-')用法与js一致
toList() 和var set = new Set() // 去掉重复数据 set.addAll([数组]);得到的是一个对象,再.toList();转化为数组;


  List myList = ['香蕉', '苹果', '李子', '香蕉'];
  // myList.add('橘子'); // 新增数据   增加一个
  // print(myList);

  // myList.addAll(['桃子', '西瓜']); // 拼接数组   增加多个
  // print(myList);

  // print(myList.indexOf('香蕉')); // 查找数据,成功返回数组索引值,失败返回-1;重复数据,指挥删除从左向右第一个发现的

  // print(myList.remove('香1蕉')); // 删除数据,只会删除从左向右第一个发现的
  // print(myList);

  // print(myList.removeAt(0)); // 删除数据,只会删除从左向右第一个发现的
  // print(myList);

  // myList.fillRange(1, 2, '新苹果'); // 从1开始到2结束但不含下标2

  // myList.insert(0, '小香蕉'); // 插入一条数据
  // myList.insertAll(0, ['小苹果', '小西瓜']); // 插入多条数据

  // String str = myList.join(','); // 转成字符串
  // print(str);
  // print(str.split(',')); // 转成数组

  // set 去重复方法 及tolist方法的使用;
  // var set = new Set();
  // set.addAll(myList);
  // print(set); // 显示的是去重复后的对象 {香蕉, 苹果, 李子}
  // print(set.toList()); // 对象转数组


  print(myList);

5.6.定义Maps类型

  // 1.第一种定义Maps的方式
  var person = {"name": "张三", "age": 12};  // 此处的var 可以换成Map 也是可以实现定义的
  print(person['name']);

  // 2.第一种定义Maps的方式
  var person2 = new Map();
  person2['name'] = '颤三2';
  person2['age'] = 11;
  print(person2['name']);
  print(person2['age']);

注意:跟js中json对象有点一致;再dart中定义maps key 必须加引号;person[‘name’]

5.7.Maps常用属性和方法

1.常用属性
keys 获取所有的key值
values 获取所有的value值
isEmpty 是否为空
isNotEmpty 是否不为空

  var person = {"name": '颤三', "age": 20};
  print(person.keys.toList());
  print(person.values.toList());
  print(person.isEmpty);
  print(person.isNotEmpty);

2.常用方法

addAll({ ...}) 合并映射 给映射内新增属性
remove(key) 删除指定key的数据
containsValue 查看映射内的值

  var person = {"name": '颤三', "age": 20};
  person.addAll({"weight": 150, "height": 160});
  print(person);
  person.remove('weight');
  print(person);
  print(person.containsValue('颤三')); // 返回值为true和false;

5.8.Map List 常用的循环语句 forEach map where any every 详解;

数组使用

// // forEach  把每一个都展示出来
  // persons.forEach((item) {
  //   print(item);
  // });

  // // map 需要配合return生成一个字符串通过toList()转化为数组
  // var newPersons = persons.map((item) {
  //   return item;
  // });
  // print(newPersons.toList());

  // // where 需要配合return生成一个字符串通过toList()转化为数组
  // var newPersons = persons.where((item) {
  //   return item == '张三';
  // });
  // print(newPersons.toList());

  // // any  需要配合return使用,任何一个复合条件就会返回一个bool
  // var newPersons = persons.any((item) {
  //   return item == '张三';
  // });
  // print(newPersons);

  // // 简写
  // var newPersons = persons.any((item) => item == '张三');
  // print(newPersons);

  // every  需要配合return使用,任何每一个符合条件就会返回一个bool,与any正好想法
  // var newPersons = persons.every((item) {
  //   return item == '张三';
  // });
  // print(newPersons);
  // // 简写
  // var newPersons = persons.every((item) => item == '张三');
  // print(newPersons);

map使用

 person.forEach((key, value) {
    print("$key --- $value");
  });

注意:map使用遍历与list的区别就在于map有两个参数,key和value ,list只有一个参数value;

5.9.is判断Dart数据类型

var str = 'aimee';
  if (str is String) { // 有的编辑器会有波浪线提示,请忽略,此处就是为了体现is的用法
    print('str 是string类型');
  } else if (str is int) {
    print('str 是int类型');
  } else {
    print('其他类型');
  }

6.Dart 运算符 条件判断 类型转换

6.1.Dart运算符

1.算数运算符 “ + - * % 求余 取整

  var num1 = 13;
  var num2 = 5;
  print(num1 + num2); // 加
  print(num1 - num2); // 减
  print(num1 * num2); // 乘
  print(num1 / num2); // 除
  print(num1 % num2); // 求余
  print(num1 ~/ num2); // 取整

2.关系运算符 " == (等于) !=(不等于) >(大于) >=(大于等于) <(小于) <=(小于等于) `"

  var num1 = 13;
  var num2 = 5;
  print(num1 > num2); // 大于
  print(num1 < num2); // 小于
  print(num1 >= num2); // 大于等于
  print(num1 <= num2); // 小于等于
  print(num1 == num2); // 等于
  print(num1 != num2); // 不等于

3.逻辑运算符 “ !(取反) &&(并且) ||(或者)” 与js用法一致不详细举例了;
4.赋值运算符 “ = (等于) ??=(值为空则赋值=右侧,不为空就不赋值了)

4.1   ‘ = ’    赋值执行顺序是从右向左,先计算后赋值;
4.2   var b; b??=23;          // 结果为23  ,   b为空则赋值为23
      var b =10; b??=23;      // 结果为10  ,   b不为空则取值10

5.复合赋值运算符

  var a = 20;
  a += 10; // 复合赋值加法 a=a+10
  a -= 10; // 复合赋值减法 a=a-10
  a *= 10; // 复合赋值乘法 a=a*10
  // a /= 2; // 复合赋值除法 a=a/10   // 这里报了一个错误,无法理解
  a %= 10; // 复合赋值求余 a=a%10
  a ~/= 10; // 复合赋值取证 a=a~/10
  1. " ++ --" 在赋值运算中,++在后面就是先赋值再计算,++在前面就是先计算在赋值;
var a = 10;
var b = a++; // a++意思就是a = a+1; ++在后面就是先给b赋值再计算,++在前面就是先计算在赋值给b;

6.2.Dart条件判断

1.if else switch case //跟js一个用法;
2.三木运算符 //跟js一个用法;
3.??运算符 //跟上面4.2一个意思 ,为空就等有??后面的,不为空就用原来的;

6.3.Dart类型转换

  1. toString()强制转化为字符串类型;
  var num = 123;
  var num1 = num.toString();
  print(num1 is String);
  1. int.parse() ;double.parse()强制转化为int和double类型;
  var num = '111';
  var num1 = int.parse(num);
  var num2 = double.parse(num);
  print(num1);
  print(num2);
  print(num1 is int);
  print(num2 is double);
  1. isEmpty和try catch的使用
  var price = '111';
  try {
    var myPrice = double.parse(price);
    print(myPrice);
  } catch (err) {
    print('0.0');
  }

 var a = '';
  if (a.isEmpty) {
    print('a 是空的');
  } else {
    print('a 不是空的');
  }
var b = 0/0;
if(b.isNaN){
	print('NaN ');
}

7.Dart 中的遍历for while 和do while break continue

与js中使用方法一毛一样;不记录了;我是个前端过来的,所以这些还是比较熟悉,你不熟悉就去自己看看;

在这里插入图片描述

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

8.1.自定义函数,自定义方法

自定义函数 在main函数外面定义就是全局函数,在哪里都能用;
在main函数内定义的函数就是main的作用域函数,只能在main函数内使用,超出作用域不可用;
自定义的函数要是有返回值必须是有return 搭配使用;
没有返回值的自定义函数可以写void 也可以什么都不写直接写函数名称;
自定义函数名称需要使用驼峰命名规则,第一个单词首字母小写,以后单词首字母大写;

void main() {
  /***
   * 1**.定义有返回值和没有返回值的方法**
   */
  void sayHello() {
    // 定义没有返回值的函数
    print('hello world');
  }

  String sayString() {
    // 定义有返回值的函数
    return 'hello string';
  }

  sayHello();
  print(sayString());

  /***
   * 2.定义局部作用域
   * 在sayWord方法内还可以定义word方法,新定义的word方法只能在sayWord内使用
   */

  sayWord() {
    // word(); // 不能使用 得先定义后使用 Error: Can't declare 'word' because it was already used in this scope.
    word() {
      print('我的作用域只能在sayWord内使用,超出报错!');
    }

    word(); // 能使用
  }

  sayWord();
  // word();// 报错,超出作用域了 Error: Method not found: 'word'

  sayChina(); // 调用全局自定义方法;
}

/**
 * 全局方法
 * 
 */
sayChina() {
  print('你好 ,我的中国');
}

8.2.函数传参(必填参数)

void main() {
  int sum(int b) { // int 规定接到参数的类型,且必须为这个类型
    int count = 0;
    for (var i = 1; i <= b; i++) {
      count += i;
    }
    return count;
  }
  // print(sum('100')); // 报错 Error: The argument type 'String' can't be assigned to the parameter type 'int'.
  print(sum(100)); // 必须传int类型
}

8.3.函数传参可选参数[int? age,String? sex]

void main() {
  String sayUserInfo(String name, [int? age, String? sex]) {
    // 规定必须有一个name参数,参数age和参数sex是可选参数
    String ageN = age != null ? (age.toString() + '岁') : '保密';
    String sexN = age != null ? sex.toString() : '保密';
    return "姓名:$name ----年龄:$ageN ----性别:$sexN";
  }

  print(sayUserInfo('张三')); // 姓名:张三 ----年龄:保密 ----性别:保密
   print(sayUserInfo('张三', 12, 'girl')); //姓名:张三 ----年龄:12岁 ---性别:girl
}

8.4.函数传参(默认参数[String? sex = ‘boy’])

String sayUserInfo(String name, [int? age, String? sex = 'boy']) {
    // 规定必须有一个name参数,参数age和参数sex是可选参数
    String ageN = age != null && age > 0 ? (age.toString() + '岁') : '保密';
    String sexN = sex == 'gril' || sex == 'boy' ? sex.toString() : '保密';
    return "姓名:$name ----年龄:$ageN ----性别:$sexN";
  }

  print(sayUserInfo('张三')); //姓名:张三 ----年龄:保密 ----性别:boy
  print(sayUserInfo('张三', 22, 'begoy')); // 姓名:张三 ----年龄:22岁 ----性别:保密

8.5.函数传参(命名参数)

void main() {
  String checkInfo(String name, {int? age, String? sex = '男'}) {
    String tips = '';
    if (age == null) {
      tips = "姓名:$name,年龄:保密,性别:$sex";
      return tips;
    }
    tips = "姓名:$name,年龄:$age,性别:$sex";
    return tips;
  }

  print(checkInfo('颤三', age: 22, sex: '男'));
  print(checkInfo('颤三', sex: '女'));
  print(checkInfo('颤三', age: 22));
  print(checkInfo('颤三'));
}

8.6.把方法当作参数


void main() {
  void sayHello() {
    print('我说了一句你好');
  }

  void person(xingcan) {  // 形参
    xingcan(); // 调用形参
  }

  person(sayHello); // 把一个函数当作一个参数传出去
}

8.7.箭头函数,匿名方法,自执行方法;

箭头函数
alist.forEach((item) => item % 2 == 0 ? item * 2 : item)

alist.forEach((item) => {
  retun  item % 2 == 0 ? item * 2 : item
})

匿名函数

  var hello = (String name) {
    print('$name say hello');
  };
  hello('zzc');

自执行函数;没有调用自己就执行了;

 (() {
    print('hello');
  })();

方法的递归 注意:切记要注意return 要不就死循环了;

 var sum = 0;
  add(int n) {
    sum = sum + n;
    if (n == 1) {
      print(sum);
      return;
    }
    add(n - 1);
  }

  add(100);

9.Dart 中的类 对象

9.1.Dart 面向对象编程(oop)三大基础特性:继承、封装、多态;

在这里插入图片描述

9.2.Dart 自定义类


// 声明一个类
class Person {
  // 定义变量
  String name = '张三';
  int age = 22;
  // 定义类的方法
  getInfo() {
    print("姓名:${this.name} --------- 年龄:${this.age}");
  }
  setInfo(String name, {int age = 18}) {
    this.name = name;
    this.age = age;
  }
}

void main() {
  // 实例化类的两种方法
  var person = new Person();

  Person person1 = new Person();
  person1.getInfo();

  person.setInfo('王五', age: 30);
  person.getInfo();
}

9.3.Dart中类的构造函数的理解

默认构造函数(在类中与类名称相同的方法叫做构造方法),传参需要在实例化过程中就传参; 默认构造函数只能写一个;

// 声明一个类

class Person {
  // 定义变量
  String name = '';
  int age = 0;

  // 默认构造函数(与类名称相同的方法叫做构造方法)
  // Person(String name, int age) {
  //   print('创建person实例时会被触发');
  //   this.name = name;
  //   this.age = age;
  // }
  // 默认构造函数简写
  Person(this.name, this.age);
  // 定义类的方法
  void getInfo() {
    print("姓名:${this.name} --------- 年龄:${this.age}");
  }
}

void main() { 
  Person person = new Person('zhangsan', 20);
  person.getInfo();
  Person person1 = new Person('zhangsan1', 29);
  person1.getInfo();
}

9.4.Dart类的命名构造函数

命名走早函数可以有多个
使用方法:Perso.now();这个now就是命名构造函数;


// 声明一个类

class Person {
  // 定义变量
  String name = '';
  int age = 0;
  // 默认构造函数 唯一
  Person(this.name, this.age);
  // 命名构造函数  可以多个
  Person.setInfo(String name, int age) {
    this.name = name;
    this.age = age;
  }

  Person.addUserAge(String name, int age) {
    this.name = name;
    this.age = age + 10;
  }
  // 定义类的方法
  void getInfo() {
    print("姓名:${this.name} --------- 年龄:${this.age}");
  }
}

void main() {
  Person person = new Person.setInfo('王五', 30);
  person.getInfo();

  var person2 = new Person.addUserAge('LISI', 44);
  person2.getInfo();
}

9.5.Dart 抽离封装成一个单独的类,方便管理,及重命名库,部分引入库

import 'lib/person.dart' as lib; // 重命名库 “
import 'lib/person.dart' show getInfo; // 只引入该库中的getInfo方法;
import 'lib/person.dart' hide getInfo; // 只隐藏该库中的getInfo方法;

在根目录下创建lib文件夹,在这文件夹下创建一个person.dart把整个person类放在这里面

class Person {
  // 定义变量
  String name = '';
  int age = 0;
  // 默认构造函数 唯一
  Person(this.name, this.age);
  // 命名构造函数  可以多个
  Person.setInfo(String name, int age) {
    this.name = name;
    this.age = age;
  }

  Person.addUserAge(String name, int age) {
    this.name = name;
    this.age = age + 10;
  }
  // 定义类的方法
  void getInfo() {
    print("姓名:${this.name} --------- 年龄:${this.age}");
  }
}

在需要使用的地方引入 import 'lib/person.dart';
在需要使用的地方引入 并重命名 import 'lib/person.dart as lib;'

import 'lib/person.dart';
//import 'lib/person.dart' as lib; // 重命名库
//import 'lib/person.dart' show getInfo; // 只引入该库中的getInfo方法;
//import 'lib/person.dart' hide getInfo; // 只隐藏该库中的getInfo方法;
void main() {
  Person person = new Person.setInfo('王五', 30);
  person.getInfo();

  var person2 = new Person.addUserAge('LISI', 44);
  person2.getInfo();
  
  lib.Person p2 = new lib.Person('王三',20); //重命名后使用自定义库
  p2.getInfo();
  
}

9.6. Dart 类的私有属性和私有方法需要使用_进行定义

类未被抽离出去 _属性或方法失效,还是能访问到;

class Animals {
  String _name = '';
  int age = 0;
  Animals(this._name, this.age);
  wang() {
    print("${this._name}在叫 ${this.age}");
  }
}

void main() {
  Animals animal = new Animals('小狗', 22);
  print(animal._name);  // 如果类型和调用的在同一个文件夹内,可以访问的到;如果抽离出去不同的文件夹,就访问不到了;
  animal.wang();
}

类被抽离出去 _name只能在类内使用,相当于局部变量局部属性局部函数
想访问_name或私有方法,需要在类中声明一个中间方法返回
1.抽离到/lib/animal.dart

class Animals {
  String _name = '';
  int age = 0;
  Animals(this._name, this.age);
  wang() {
    print("${this._name}在叫 ${this.age}");
  }
}

2.抽离到/lib/animal.dart

import 'lib/animal.dart';

void main() {
  Animals animal = new Animals('小狗', 22);
  // print(animal._name);  // 如果类型和调用的在同一个文件夹内,可以访问的到;如果抽离出去不同的文件夹,就是该类的私有属性了,不能访问到了;
  animal.wang();
}

9.7.Dart中的get 和set 的使用

get和 set 与普通方法的区别就是没有(),普通方法有(),get 和 set 修饰的没有()可以当参数赋值 this.name = 'sansan'; print(this.name);get 和 set 可以当做方法但是没有()

class Reac {
  int height = 0;
  int width = 0;
  Reac(this.height, this.width);
  get area { // get 这样写
    return this.height * this.width;
  }

  set setNewHeight(int height) {  //  set 这样写
    this.height = height;
  }
}

void main() {
  var reac = new Reac(10, 10);
  print(reac.area); // get这是调用
  reac.setNewHeight = 4; // set 这样调用
  print(reac.area);
}

10.Dart中的类 静态成员 操作符 类的继承

10.1.Dart中的静态成员(static) 修饰

1.使用static 关键字来定义静态属性和静态方法;

class Person {
  static String name = '张三'; // 静态属性
  int age = 20; // 非静态属性

  //静态方法
  static void sayHello() {
    print("静态方法 sayHello");
  }

  //  非静态方法
  void sayWord() {
    print("我是非静态方法");
  }
}

2.静态方法不能访问非静态属性和方法,只能访问静态属性和静态方法;

class Person {
  static String name = '张三'; // 静态属性
  int age = 20; // 非静态属性

  //静态方法
  static void sayHello() {
    // 调用静态属性和静态方法
    say();
    print('静态方法调用同一类下的静态属性name:${name}');
    // 调用非静态属性和方法 报错无法正常运行
    // this.sayWord();
    // print('静态方法调用同一类下的非静态属性age:${this.age}');
  }

  //  静态方法
  static void say() {
    print("我是静态方法,被静态方法调用了");
  }

  //  非静态方法
  void sayWord() {
    print("我是非静态方法");
  }
}

void main() {
  Person.sayHello();
}


3.非静态方法可以访问同一类下的静态属性和方法(去掉this直接使用),也可以访问非静态属性和方法(建议有this);


class Person {
  static String name = '张三'; // 静态属性
  int age = 20; // 非静态属性

  //静态方法
  static void sayHello() {
    print("静态方法 sayHello");
  }

  //  非静态方法
  void say() {
    print("我是非静态方法");
  }

  //  非静态方法 可以调用静态属性和方法 也可以调用非静态属性和方法
  void sayWord() {
    print("我是非静态方法");
    // 调用静态属性和静态方法
    sayHello();
    print('非静态方法调用同一类下的静态属性name:${name}');
    // 调用非静态属性和方法
    print("非静态方法调用同一类下的非静态属性age:${this.age}");
    this.say();
  }
}

void main() {
  // // 调用非静态属性
  Person person = new Person();
  print("调用非静态属性age:${person.age}"); // 调用非静态属性
  person.sayWord(); //调用非静态方法sayWord
}

4.静态方法的调用 - > Person.name Person.show();

void main() {
  // 调用静态属性
  print(Person.name); 
  // 调用静态方法
  Person.sayHello();
}

5.非静态方法的调用 -> Person p = new Person();person.show();

void main() {
  // 调用非静态属性
  Person person = new Person();
  print("调用非静态属性age:${person.age}"); // 调用非静态属性
  person.sayWord(); //调用非静态方法sayWord
}

10.2 Dart中的对象操作符? as is ..

? -------> 条件运算符(了解)

class Person {
  String name = '张三';
  int age = 20;
  Person(this.name, this.age);
  void showInfo() {
    print('${this.name} ---------- ${this.age}');
  }
}

void main() {
  var p;
  p = new Person('小红', 11);
  p?.showInfo(); // p 存在就会调用showInfo方法
}

as ------> 类型转换

class Person {
  String name = '张三';
  int age = 20;
  Person(this.name, this.age);
  void showInfo() {
    print('${this.name} ---------- ${this.age}');
  }
}

void main() {
  var p;
  p = '';
  p = new Person('小明', 18);
  (p as Person).showInfo(); // 强制转化为Person类型
}

is ------> 类型判断

class Person {
  String name = '张三';
  int age = 20;
  Person(this.name, this.age);
  void showInfo() {
    print('${this.name} ---------- ${this.age}');
  }
}

void main() {
  Person person = new Person('张三', 22);
  person.showInfo();
  if (person is Person) {
    print('person.is.new 1 person!');
  }
  print(person is Object);
}

.. ------> 联级操作(连缀操作)

class Person {
  String name = '张三';
  int age = 20;
  Person(this.name, this.age);
  void showInfo() {
    print('${this.name} ---------- ${this.age}');
  }
}

void main() {
  var p = new Person('小红', 11);
  p.showInfo();
  // 这段代码等价于 下面代码 sart
  p.age = 25;
  p.name = 'aimee';
  p.showInfo();
  // 这段代码等价于 下面代码 end

  p
    ..name = '小明'
    ..age = 12
    ..showInfo(); // 连缀 只在最后一个加分号;
}

10.3.面向对象三大特性之一 继承

1.子类使用extends关键字来继承父类;
2.子类会继承肺类里面可见的属性和方法 但不会继承构造函数;
3.子类能复写父类的方法 getter 和 setter;

// 子类继承使用extends;
// 子类可以调用父类的方法和属性;
// 复写父类方法,就是写一个方法名跟父类方法名义一样的函数;
// 子类自定义方法调用父类方法用super.say();
class Person {
  String name;
  int age;
  Person(this.name, this.age); // 构造函数 唯一
  Person.hello(this.name, this.age); // 命名构造函数 可以多个
  void showInfo() {
    print('${this.name} ---------- ${this.age}');
  }
  void say(){
  	print("hello say");
  }
}

class Student extends Person {
  String sex = '男';
  // Student(String name, int age, String sex) : super(name, age) {  // 完全接参跟父类构造器一样
  Student(String name, int age, String sex) : super.hello(name, age) {  // 子类构造器新增加了参数
    this.sex = sex;
  }
  void speak() {
    print('${this.name} - ${this.age} - ${this.sex} 你好我是子类自定义的方法');
    super.say(); // 子类自定义方法调用父类方法;
  }

  // 复写父类方法 子类调用时候,有限调用子类复写后的方法;
  @override
  void showInfo() {
    print('${this.name} - ${this.age} - ${this.sex} 你好我是子类复写父类的方法');
  }
}

void main() {
  Student stu = new Student('张磊磊', 22, '男');
  stu.showInfo(); // 调用继承父类的方法 如果子类复写(父类方法名和子类方法名一样)了该方法则优先调用子类的方法;
  stu.speak(); // 调用自己定义的方法
}

11.Dart中 抽象类 多态 和接口

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

!!!! 在抽象方法中没有方法体{}的方法叫做抽象方法!!!!

在这里插入图片描述

abstract class Animal {
  run(); // 抽象方法 定义标准,类似于告诉,所有继承这个类的子类必须有这个方法,跟抽象类中的普通方法的区别就是没有方法体即{};
  eat(String foods); // 抽象方法 定义标准,类似于告诉,所有继承这个类的子类必须有这个方法,跟抽象类中的普通方法的区别就是没有方法体即{};
  void goHome() {  // 抽象类中的普通方法这样定义
    print('我是抽象类中定义的普通方法 goHome!');
  }
}

class Cat extends Animal {
  @override // 重写抽象方法
  eat(String foods) {
    print('父类中定义的抽象类,子类重写,猫吃${foods}');
  }

  @override // 重写抽象方法
  run() {
    print('父类中定义的抽象类,子类重写,猫跑了');
    goHome();
  }
}

class Dog extends Animal {
  @override // 重写抽象方法
  eat(String foods) {
    print('父类中定义的抽象类,子类重写,狗吃${foods}');
  }

  @override // 重写抽象方法
  run() {
    print('父类中定义的抽象类,子类重写,狗跑了');
    goHome(); // 调用父类中的普通方法
  }
}

void main() {
  Dog dog = new Dog();
  dog.run();
  dog.eat('骨头');
  Cat cat = new Cat();
  dog.run();
  cat.eat('小鱼');
}

11.2 多态

允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果。
子类的实现赋值给父类的引用。
简而言之:父类定义方法不去实现,让继承他的子类去实现,每个子类有不同的表现。

abstract class Animal {
  eat(); // 抽象方法 定义标准,类似于告诉,所有继承这个类的,必须有这个方法
}

class Cat extends Animal {
  @override // 重写抽象方法
  eat() {
    print('父类中定义的抽象类,子类重写,猫吃鱼');
  }

  run() {
    print('父类中定义的抽象类,子类重写,猫跑了');
  }
}

class Dog extends Animal {
  @override // 重写抽象方法
  eat() {
    print('父类中定义的抽象类,子类重写,狗吃肉 ');
  }

  run() {
    print('父类中定义的抽象类,子类重写,狗跑了');
  }
}

void main() {
  // 这个就没有实现多态,直接调用子类的方法了;
  Dog dog = new Dog();
  dog.eat();
  dog.run();
  // 这个cat就只能调用父类中声明的抽象方法,但是子类中的eat赋值给了父类中的eat;
  Animal cat = new Cat();
  cat.eat();
}

11.3 接口 用implements关键词实现 且封装

在这里插入图片描述
实现案例 ,想两个链接发数据

在lib下,新建oss.dart;

abstract class Db {
  late String url;
  add(String data);
}
// 使用接口
class Oss implements Db {
  @override
  late String url;

  @override
  add(String data) {
    print('我这里是Oss类向${url}新增了数据:${data}');
  }
}

在lib下,新建sql.dart;

abstract class Db {
  late String url;
  add(String data);
}
// 使用接口
class mySql implements Db {
  @override
  String url;

  mySql(this.url); // 子类构造函数

  @override
  add(String data) {
    print('我这里是mySql类向${url}新增了数据:${data}');
  }
}

随意新建使用接口

import 'lib/sql.dart';

void main() {
  var sql = new mySql('www.baidu.com'); // 实例化对象
  sql.add('我是渣男啊!'); //调用子类方法
  var oss = new Oss();  // 实例化对象
  oss.url = 'www.qq.com'; // 子类直接赋值
  oss.add('我也是渣男啊!'); // 调用子类方法
}

11.4 使用多个接口用逗号分开

class Anima implements Animal, Eat {}

abstract class Animal {
  late String name;
}

abstract class Eat {
  eat(String foods);
}

class Anima implements Animal, Eat {
  @override
  String name;

  Anima(this.name);
  @override
  eat(String foods) {
    print('我是${this.name}  我吃了${foods}');
  }
}

void main() {
  Anima cat = new Anima('小猫');
  cat.eat('小鱼儿');
  Anima dog = new Anima('小狗');
  dog.eat('大骨头儿');
}

12 mixins混入特性的使用!mixins和继承一起使用!

实现多继承的功能!
条件如下图
解析:
1.只能是干干净净的class ,不能是抽象类;
2.被mixins的类不能有构造函数,不能继承其他类;
3.一个类可以混入多个类,with A,B还以继承再混入 extends C with A ,B;
4.他不是继承也不是接口;
5.mixins的实例类型是什么?很简单,mixins的类型就是超类的子类型;
在这里插入图片描述

class Animal {
  late String name;
  Animal(this.name);
}

class Eat {
  eat(String foods) {
    print('我吃了${foods}了,触发Eat方法了');
  }
}

class Play {
  play(String ball) {
    print('我玩了${ball}了,触发Play方法了');
  }
}

class Anima extends Animal with Eat, Play {
  Anima(String name) : super(name);

  @override
  play(String ball) {
    print('${this.name}玩了${ball}了,触发Play方法了');
  }

  @override
  eat(String foods) {
    print('${this.name}吃了${foods}了,触发Eat方法了');
  }
}

void main() {
  Anima an = new Anima('Aimee');
  an.eat('苹果');
  an.play('篮球');
}

注意:如果复写方法很多,按照 最后调用的覆盖前面的方法;

13. 泛型类 泛型方法 泛型接口 泛型mixins 的使用

自己的理解:打印接到的参数,传参可能是string ,int ,double,map,list 各式各样的,不能一个参数类型写一个方法去调用,就用到泛型,你发什么,我就接什么
注意:泛型的使用就是为了避免冗余代码,比如因为类型不同,写了两个类;对传参和接参进行校验

定义泛型方法:

T Hello<T>(T value){
	return value;
}

第一个 T 代表返回值返回的是个泛型;这个不指定!
第二个 T 代表调用方法时必须指定该类型;
第三个 T 代表接收参数是个泛型;

// 这里定义 什么类型都能收到;前提是创建的时候没指定类型;创建指定类型,就只能接收到指定类型的参数;
class SaySomething<T> {
  specak(T things) {
    print('定义了泛型类,且说了${T}类型话-${things}');
  }
}

// mixin 泛型使用
class Person<T> with SaySomething<T> {
  var name;
  Person(this.name);
}

// 接口类型 泛型使用
class Animal<T> implements SaySomething<T> {
  var name;
  Animal(this.name);
  @override
  specak(T things) {
    print('我是${name}  我的叫声${things}');
  }
}

//继承 泛型使用
class Student<T> extends SaySomething<String> {
  var name;
  Student(this.name);
}

void main(List<String> args) {
  SaySomething sayString = new SaySomething<String>();
  sayString.specak('我是字符串');
  // sayString.specak(33); // 报错

  SaySomething sayInt = new SaySomething<int>();
  sayInt.specak(12334);
  // sayInt.specak('asdfsd');// 报错

  // mixins 使用泛型
  Person person = new Person<int>('王小二');
  person.specak(11);
  // person.specak('things'); // 报错

  // 接口使用泛型
  Animal animal = new Animal<String>('小猫咪');
  animal.specak('喵喵喵');
  // animal.specak(111); // 报错

  // 继承使用泛型  初始化指定string类型 只能接到string类型了,传别的不行;
  Student stu = new Student<String>('王一博');
  stu.specak('老师好');
  // stu.specak(111); // 报错
}

14 Dart 中的库 自定义库 系统库 第三方库

在这里插入图片描述

14.1 自定义库

类抽离lib文件夹下 需要使用import 引入 ;这就叫自定义库;

import 'lib/Animal.dart';

14.2 系统内置库

import 'dart:math';// 跳转到内置库去看怎么用

void main() {
  print(max(21, 22));
}

在这里插入图片描述

14.3 async 和await的使用

async 是让方法变异步
await 是等待异步方法执行完成。

只有async方法才能使用await关键字调用方法
如果调用别的async方法必须使用await关键字

void main() async { // 只有async方法才能使用await关键字调用方法
  await sayHello(); // 如果调用别的async方法必须使用await关键字
}

// 异步方法
sayHello() async {
  print('hello world');
}

注意:异步方法改成同步方法使用await;

14.4 第三方库的使用

1.下面网址找到要用的库。

https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/

2.根目录创建文件pubspec.yaml 文件,内容如下。

name: my_wechat
description: A new Flutter project.

3.配置 dependencies,查看文档installing 。
dependencies:
http: ^0.13.4

4.运行 pub get 获取远程库。

5.看文档引入库使用。

在这里插入图片描述

15.Dart 2.13之后的一些新特性 Null safety、late 关键字、空类型声明符?、非空断言!、required 关键字;

15.1 Null safety 对应中文 空安全 、?可控类型

? 可空类型 : int? a = 1; // a 是一个可空类型
? 可空方法 : String? sayHello(things){} // sayHello 是一个可空方法
! 类型断言 : print(name!.length); // 类型断言:如果name不是null会打印长度,如果等于null会抛出异常;
在这里插入图片描述

// 方法可空
  String? sayHello(things) {
    print(things != null);
    if (things != null) {
      return things;
    }
    return null;
  }
  print(sayHello('艾米的猫儿-傻钢'));
  
  // 类型可空
  
   int? a = 1; // A是一个可空类型
   a = null; // 空安全  校验
   print(a);

  // 类型断言!
  String? name = 'this.is.str';
  // name = null;
  print(name!.length); // 类型断言:如果name不能与null会打印长度,如果等于null会抛出异常;

15.2 late 关键字 主要用于类中自定义变量延迟初始化

也就是类中未给变量初始化会报错,变量定义加上late这个字段,就是标识这个字段,稍后就赋值通过方法setName来赋值name和age;

late String name; //延迟初始化值

class Person {
  late String name;
  late int age;
  void setName(String name, int age) {
    this.name = name;
    this.age = age;
  }
}

void main() {
  Person person = new Person();
  person.setName('沙钢', 11);
}

15.3 required 关键字 内置修饰符 必须传参的意思

class Person {
  String name;
  int? age;
  Person({required this.name, this.age}); // 这里是简写命名传参
  void printName() {
    print("${this.name} --- ${this.age == null ? '未知' : this.age}");
  }
}

void main() {
  Person person = new Person(name: '颤三', age: 20); // 必须命名传参
  Person persons = new Person(name: '颤三');
  person.printName();
  persons.printName();
}

总结

提示:此文章为前端学习flutter过程,如有歧义期望各位大大的宝贵意见

学习Dart 基础知识 移步这里
安装flutter环境相关 移步这里
flutter基础组件使用相关 移步这里

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值