加粗样式
提示:此文章为前端学习flutter过程,如有歧义期望各位大大的宝贵意见
文章目录
- 前言
- 一、什么是Dart?
- 二、Dart使用
- 1.声明返回值为空的入口文件
- 2.Dart变量的声明及使用
- 3.Dart命名规则
- 4.Dart 常量
- 5.Dart 数据类型
- 6.Dart 运算符 条件判断 类型转换
- 7.Dart 中的遍历for while 和do while break continue
- 8.Dart 中的函数,自定义函数,可选参数,默认参数,命名参数,箭头函数,匿名函数,闭包等
- 9.Dart 中的类 对象
- 10.Dart中的类 静态成员 操作符 类的继承
- 11.Dart中 抽象类 多态 和接口
- 12 mixins混入特性的使用!mixins和继承一起使用!
- 13. 泛型类 泛型方法 泛型接口 泛型mixins 的使用<String>
- 14 Dart 中的库 自定义库 系统库 第三方库
- 15.Dart 2.13之后的一些新特性 Null safety、late 关键字、空类型声明符?、非空断言!、required 关键字;
- 总结
前言
提示:想学好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
- "
++ --
" 在赋值运算中,++在后面就是先赋值再计算,++在前面就是先计算在赋值;
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类型转换
toString()
强制转化为字符串类型;
var num = 123;
var num1 = num.toString();
print(num1 is String);
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);
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过程,如有歧义期望各位大大的宝贵意见