Dart语法下

news/2024/10/30 15:30:13/

十三、Dart中的范型

13.1 范型方法

通俗理解: 范型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持(类型校验)

案例1:

  • 定义一个函数只能返回String类型的数据
String getStringData(String value){return value;
}

案例2:

  • 同时支持返回String和int类型
String getStrData(String value){return value;
}
int getIntData(int value){return value;
}

案例3: 同时返回String类型和number类型,不指定类型可以解决这个问题

getMixData(value){return value;
}

案例4:

  • 不指定类型放弃了类型检查.我们现在想实现的是传入什么,返回什么.
  • 比如传入number,类型必须返回number类型,传入String类型必须返回String类型.要求类型一致.
    • 因此引入范型
      • 用T对返回值类型进行校验
      • 对返回值类型不进行校验
 //T校验返回值T getMixDatas<T>(T value){return value;}//不校验返回值getMixDatal<T>(T value){return value;}
    • 案例调用
main(){print(getMixDatas(2222));print(getMixDatas("11111"));
}
    • 但是这么操作还是没有实现类型一致性,既然引入了范型,那么我们在调用的时候添加上约束就行
print(getMixDatas<String>("3333"));
print(getMixDatas<int>(4444));

13.2 范型在类中的用法.

  • 集合List在范型类的用法

案例:

把下面类转换成范型类,要求MyList里面可以增加int类型的数据,也可以增加String类型的数据.但是每次调用增加的类型要统一.

class MyList{List list = <int>[];void add(int value){this.list.add(value);    }List getList(){return list;    }
}
main(){MyList l = new MyList();l.add(1);l.add(12);l.add(5);print(l.getList());//[1,12,5]
}
    • 修改后的实现部分
class MyList<T>{List list = <T>[];void add(T value){this.list.add(value);    }List getList(){return list;    }
}
    • 案例调用
List list1 = new List<int>.filled(2,0);//初始化list1列表,长度为2,填充值为0,也就是[0,0]
list1[0] = 11111;
list1[1] = 22222;
print(list1);//[11111, 22222]

13.3 范型接口

案例1:

    • 两个抽象类ObjectCache、StringCache
    • 对两个抽象类进行复用性精简.
abstract class ObjectCache {getByKey(String key);void setByKey(String key,Object value);
}
abstract class StringCache{getByKey(String key);void setByKey(String key,String value);
}
//将上述两个抽象类进行复用性精简
abstract class Cache<T> {getByKey(String key);void setByKey(String key,T value);
}

案例2:

实现数据缓存的功能: 有文件缓存和内存缓存.内存缓存和文件缓存按照接口约束实现.

    • 1、定义一个范型接口,约束实现它的子类必须有getByKey(key)和setByKey(key,value)
    • 2、要求setByKey的时候的value类型和实例化子类的时候指定的类型一致.

根据要求,首先需要定义两种类型的缓存,通过对缓存抽象类的实现,定制两种类型的类.

abstract class Cache<T>{getByKey(String key);void setByKey(String key,T value);
}
class FileCache<T> implements Cache<T>{@overridegetByKey(String key){return null;    }@overridevoid setByKey(String key,T value){print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");    }
}
class MemoryCache<T> implements Cache<T>{@override getByKey(String key){return null;    }@overridevoid setByKey(String key,T value){print("我是内存缓存 把key=${key} value=${value} - 写入到了内存中");    }
}
  • 根据编写的类,对其进行调用测试
void main(){MemoryCache m = new MemoryCache<String>();m.setByKey('index','首页数据');//我是内存缓存 把key=index  value=首页数据 -写入到了内存中MemoryCache n = new MemoryCache<Map>();n.setByKey('index',{"name": "张三", "age": 20});//我是内存缓存 把key=index  value={name: 张三, age: 20} -写入到了内存中
}

13.4 总结

  • 范型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持(类型校验)

十四、Dart中的库

14.1 Dart中的库

前面介绍Dart基础知识的时候基本上都是在一个文件里面编写Dart代码,但实际开发中不可能这么写,模块化很重要,所以这就需要使用到库的概念.

  • 在Dart中,库的使用是通过import关键字引入的.
  • library指令可以创建一个库,每个Dart文件都是一个库,即使没有使用library指令来指定.

Dart中的库主要有三种:

  1. 我们自定义的库
    1. import 'lib/xxx.dart';
  2. 系统内置库
    1. import 'dart:math';
    2. import 'dart:io';
    3. import 'dart:convert';
  3. Pub包管理系统中的库
    1. Page 1 | Top packages、Page 1 | Top packages、Search results for sdk:flutter
    2. 需要在自己项目根目录下新建一个pubspec.yaml
    3. 在pubspec.yaml文件,然后配置名称,描述,依赖等信息.
    4. 然后运行pub get 获取包下载到本地
    5. 项目中引入库 import 'package:http.dart' as http;

例如: 一个pubspec.yaml文件

name: xxx
description: A new flutter module project.
dependencies:http: ^0.12.0+2date_format: ^1.0.6
environment:sdk: '>=2.10.0 <3.0.0'

14.2 Dart中导入自己本地库

在一个模块中导入自己本地库,也就是两个文件的调用关系,比如在lib文件夹下创建的Animal.dart模块,在main.dart模块中需要使用,那么只需要给相对路径即可.

import 'lib/Animal.dart';
main(){var a=new Animal('小黑狗', 20);print(a.getName());
}

14.3 导入系统内置库

如果我们想要使用系统库,系统库的前缀是 'dart:',在它的后面加上你要使用的哪个系统库.command+鼠标左键即可点进去一个库对其内容进行查看.

import 'dart:math';
main(){print(min(12,23)); //12print(max(12,25)); //25
}

14.4 导入系统内置库实现请求数据

一个网络数据的请求过程:

  1. 创建HttpClient对象
  2. 创建url对象
  3. 发起请求,等待请求
  4. 关闭请求,等待响应
  5. 解码响应的内容

案例: 请求知乎最近的新闻数据

  • HttpClient是系统内置库io中的模块
  • 需要用到数据解析,使用的是convert中相关的模块
import 'dart:io';
import 'dart:convert';
void main() async{var result = await getDataFromZhihuAPI();print(result);
}
getDataFromZhihuAPI() async {//1、创建HttpClient对象var httpClient = new HttpClient();//2、创建Url对象var uri = new Uri.http('news-at-zhihu.com','/api/3/stories/latest');//3、发起请求,等待请求var request = await httpClient.getUrl(url);//4、关闭请求,等待响应var response = await request.close();//5、解码响应的内容return await response.transform(utf8.decoder).join();
}
  • 执行函数,返回请求结果如下:
{"date":"20230501","stories":[{"image_hue":"0x424f37","title":"小事 · 你见过哪些父母惊艳到你的教育方式?","url":"https:\/\/daily.zhihu.com\/story\/9761023","hint":"VOL.1483","ga_prefix":"050107","images":["https:\/\/picx.zhimg.com\/v2-4b3cb2892a38b2340b12ba33c6ff381a.jpg?source=8673f162"],"type":0,"id":9761023},{"image_hue":"0x453040","title":"有哪些知道了语源后会令人感到惊讶的英语单词?","url":"https:\/\/daily.zhihu.com\/story\/9760986","hint":"一直在路上David · 4 分钟阅读","ga_prefix":"050107","images":["https:\/\/picx.zhimg.com\/v2-f66107a7770e06616a689d6e542d2136.jpg?source=8673f162"],"type":0,"id":9760986},{"image_hue":"0xb37d7d","title":"吕秀才和郭芙蓉在一起是不是郭巨侠祝无双所认为的一时冲动?","url":"https:\/\/daily.zhihu.com\/story\/9760990","hint":"童大掌柜呢 · 8 分钟阅读","ga_prefix":"050107","images":["https:\/\/pic1.zhimg.com\/v2-889394ae433b0996ea24f6a6129d1ae8.jpg?source=8673f162"],"type":0,"id":9760990},{"image_hue":"0x547bae","title":"燕子为何会选择在人类屋檐下搭窝?","url":"https:\/\/daily.zhihu.com\/story\/9761000","hint":"知乎用户 · 2 分钟阅读","ga_prefix":"050107","images":["https:\/\/pic1.zhimg.com\/v2-ba775f62ab095a62d3c7ab512f68fba5.jpg?source=8673f162"],"type":0,"id":9761000},{"image_hue":"0x040404","title":"世界上有哪些两地相隔不远但互通必须绕一大圈的例子?","url":"https:\/\/daily.zhihu.com\/story\/9761008","hint":"莱茵行宫伯爵 · 2 分钟阅读","ga_prefix":"050107","images":["https:\/\/pic1.zhimg.com\/v2-368438800a90e5f1bdd081f3e9e1c351.jpg?source=8673f162"],"type":0,"id":9761008},{"image_hue":"0x7c643f","title":"面粉为什么能洗出面筋?粉是怎么转化成「筋」的呢?","url":"https:\/\/daily.zhihu.com\/story\/9761018","hint":"钱程 · 1 分钟阅读","ga_prefix":"050107","images":["https:\/\/picx.zhimg.com\/v2-d798a6d979126c6ce16f573daced0ee1.jpg?source=8673f162"],"type":0,"id":9761018}],"top_stories":[{"image_hue":"0x424f37","hint":"作者 \/ 文小白","url":"https:\/\/daily.zhihu.com\/story\/9761023","image":"https:\/\/picx.zhimg.com\/v2-d412fe4c9e66a9c2aaed7ad75fa6b975.jpg?source=8673f162","title":"小事 · 你见过哪些父母惊艳到你的教育方式?","ga_prefix":"050107","type":0,"id":9761023},{"image_hue":"0xafafaf","hint":"作者 \/ 真实故事计划","url":"https:\/\/daily.zhihu.com\/story\/9760980","image":"https:\/\/picx.zhimg.com\/v2-f01dedf1b9345156c61204fa3724b9ed.jpg?source=8673f162","title":"小事 · 你见过的最阴暗的事是什么?","ga_prefix":"043007","type":0,"id":9760980},{"image_hue":"0x5e6c24","hint":"作者 \/ 百花杀","url":"https:\/\/daily.zhihu.com\/story\/9760967","image":"https:\/\/pic1.zhimg.com\/v2-3263de81e79d67126d92b379ab6a5cb8.jpg?source=8673f162","title":"小事 · 你遇过的最温暖的瞬间是什么?","ga_prefix":"042907","type":0,"id":9760967},{"image_hue":"0xb39168","hint":"作者 \/ 斜绿天蛾","url":"https:\/\/daily.zhihu.com\/story\/9760874","image":"https:\/\/pic1.zhimg.com\/v2-a4bc6aa6a1c1ba806e8306d27adc8adc.jpg?source=8673f162","title":"昆虫演化真的符合进化论吗?","ga_prefix":"042807","type":0,"id":9760874},{"image_hue":"0x946d68","hint":"作者 \/ 于朝阳","url":"https:\/\/daily.zhihu.com\/story\/9760851","image":"https:\/\/pic1.zhimg.com\/v2-c95731f8815aadd68e2e7cb5c518ff4c.jpg?source=8673f162","title":"秦朝(秦国)为何迅速灭亡?","ga_prefix":"042

14.4 关于async和await

这两个关键字的使用只需要记住两点:

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

async是让方法变成异步.

await是等待异步方法执行完成.

void main() async {var result await testAsync();print(result);
}
testAsync() async {return "Hello async";
}

14.5 Dart导入pub包管理系统中的库

14.5.1 pub包管理系统简介:

1、从下面网址找到要用的库

  • Page 1 | Top packages
  • Page 1 | Top packages
  • Search results for sdk:flutter

2、创建一个pubspec.yaml文件,内容如下

    name: xxxdescription: A new flutter module project.dependencies:  http: ^0.12.0+2date_format: ^1.0.6

3、配置dependencies

4、运行pub get 获取远程库

5、看文档引入库使用

14.5.2 案例: 网络请求及响应

  • 首先导入需要用到的模块、数据解析用到 'dart:convert'
  • http请求使用了 package:http/http.dart
  • 时间格式化采用 date_format.dart
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import 'package:date_format/date_format.dart';
  • 实现部分
main() async {var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";var response = await http.get(url);if response.statusCode == 200 {var jsonResponse = convert.jsonDecode(response.body);print(jsonResponse);   }  else {print("Request failed with status: ${response.statusCode}.");    }print(formatDate(DateTime(2023,5,1), [yyyy,'**',mm,"**",dd])); //2023**05**01
}

14.6 Dart 库的重命名&Dart冲突解决

1、冲突解决

  • 当引入两个库中有相同名称标识符的时候
  • 如果是Java通常我们通过写上完整的包名称路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的.
  • 当冲突的时候,可以使用 as关键字来制定库的前缀.
  • 例如:
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
Element element1 = new Element();          // Uses Element from lib1.
lib2.Element element2 = new lib2.Element();// Uses Element from lib2.

案例:

import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;
main(List<String> args) {Person p1=new Person('张三', 20);p1.printInfo(); //Person1:张三----20lib.Person p2=new lib.Person('李四', 20);p2.printInfo(); //Person2:李四----20
}

14.7 部分导入

部分导入:

  • 如果只需要导入库的一部分,有两种模式
    • 一、只导入需要的部分,使用show关键字,如下所示
import 'package:lib1/lib1.dart
    • 二、隐藏不需要的部分,使用 hide 关键字, 如下所示
import 'package:lib2/lib2.dart' hide foo;

案例:

  • 实现这么一个模块,名叫myMath.dart
void getName(){print('张三');
}
void getAge(){print(20);
}
void getSex(){print('男');
}
  • 在使用时
    • 1、如果只想用 getAge方法,那么
import 'lib/myMath.dart' show getAge;
void main(){getAge();
}
    • 2、如果想要隐藏 getName方法,那么调用就会报错
import 'lib/myMath.dart' hide getName;
void main(){
//  getName();//调用报错getAge();
}

14.8 延迟加载

  • 也称为懒加载,可以在需要的时候再进行加载
  • 懒加载的最大好处是可以减少App的启动时间
  • 懒加载使用deferred as关键字来指定,如
import 'package:deferred/hello.dart' deferred as hello;
  • 当需要使用的时候,需要使用loadLibrary()方法来加载;
greet() async {await hello.loadLibrary();hello.printGreeting();
}

14.9 总结

1、Dart中的库主要有三种:

  1. 我们自定义的库
    1. import 'lib/xxx.dart';
  2. 系统内置库
    1. import 'dart:math';
    2. import 'dart:io';
    3. import 'dart:convert';
  3. Pub包管理系统中的库
    1. Page 1 | Top packages、Page 1 | Top packages、Search results for sdk:flutter
    2. 需要在自己项目根目录下新建一个pubspec.yaml
    3. 在pubspec.yaml文件,然后配置名称,描述,依赖等信息.
    4. 然后运行pub get 获取包下载到本地
    5. 项目中引入库 import 'package:http.dart' as http;

2、在一个模块中导入自己本地库,也就是两个文件的调用关系,比如在lib文件夹下创建的Animal.dart模块,在main.dart模块中需要使用,那么只需要给相对路径即可.

3、如果我们想要使用系统库,系统库的前缀是 'dart:',在它的后面加上你要使用的哪个系统库.

4、async和await这两个关键字的使用只需要记住两点:

    • 只有async方法才能使用await关键字调用方法
    • 如果调用别的async方法必须使用await关键字
  • async是让方法变成异步.
  • await是等待异步方法执行完成.

5、Dart导入pub包管理系统中的库

1、从下面网址找到要用的库

    • Page 1 | Top packages
    • Page 1 | Top packages
    • Search results for sdk:flutter

2、创建一个pubspec.yaml文件

3、配置dependencies

4、运行pub get 获取远程库

5、看文档引入库使用

6、冲突解决

  • 当引入两个库中有相同名称标识符的时候
  • 如果是Java通常我们通过写上完整的包名称路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的.
  • 当冲突的时候,可以使用 as关键字来制定库的前缀.

7、如果只需要导入库的一部分,有两种模式

    • 一、只导入需要的部分,使用show关键字
    • 二、隐藏不需要的部分,使用 hide 关键字

8、延迟加载

  • 也称为懒加载,可以在需要的时候再进行加载
  • 懒加载的最大好处是可以减少App的启动时间
  • 懒加载使用deferred as关键字来指定

十五、Dart 2.13后的新特性 Null safety、late关键字、空类型声明符?、非空断言!、required关键字

15.1 Null safety & 类型断言

Null safety翻译成中文的意思是空安全。

null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能。

Flutter2.2.0(2021年5月19日发布) 之后的版本都要求使用null safety。

  • ? 可空类型(相当于Swfit中的可选值Optional)
  • ! 类型断言(相当于Swift中的强制解包)

案例:

String? getData(apiUrl){if(apiUrl !=null ){return "this is server data";}return null;
}
  • 案例调用
  //1、null safetyint a=123;print(a);//123String username="张三";print(username);//张三List<String> l1=["张三","李四","王五"];print(l1);//[张三, 李四, 王五]// int b=123;  //非空的int类型// b=null;  //A value of type 'Null' can't be assigned to a variable of type 'int'// String usernameA="张三";  //非空的String类型// usernameA=null;   //A value of type 'Null' can't be assigned to a variable of type 'String'.String? usernameB="张三";   // String?  表示username是一个可空类型usernameB=null;print(usernameB);//nullint? c=123;  //  int? 表示a是一个可空类型c=null; print(c);//nullList<String> l2=["张三","李四","王五"];// l2=null;  //A value of type 'Null' can't be assigned to a variable of type 'List<String>'.List<String>? l3=["张三","李四","王五"];l3=null;  print(l3);//null//调用方法print(getData("http://www.itying.com"));//this is server dataprint(getData(null)); //null
//2、! 类型断言String? str="this is str";str=null;print(str!.length);  //null// 类型断言: 如果str不等于null 会打印str的长度,如果等于null会抛出异常printLength("str");//printLength(null);

15.2 late关键字

  • late关键字主要用于延迟初始化

案例:

  • 声明构造方法时,要求初始化成员不能为空,于是得加上late懒加载修饰
class Person {late String name;late int age;void setName(String name, int age) {this.name = name;this.age = age;}String getName() {return "${this.name}---${this.age}";}
}
void main(args) {Person p = new Person();p.setName("张三", 20);print(p.getName());
}

15.3 late接口

接口就是约定、规范

abstract class DB { //接口: 约定、规范late String uri; //数据库的链接地址add(String data);save();delete();
}
  • 在定义抽象类时,如果添加了成员变量,未初始化的情况下就会报错,这个时候我们使用late修饰,懒加载执行.

15.4 required关键词

required关键词

  • 最开始@required是注解; 现在它已经作为内置修饰符
  • 主要用于允许根据需要标记任何命名参数(函数和类),使得它们不为空.因为可选参数中必须有个 required参数或者该参数有个默认值.

案例1:

  • 如果想要age和sex可以为空,那么我们这样表示
String printUserInfo(String username, {int age=10, String sex="男"}) {//行参    return "姓名:$username---性别:$sex--年龄:$age";
}

案例2:

  • 如果想让age和sex必须有值,那么添加关键字required
String printInfo(String username, {required int age, required String sex}) {//行参    return "姓名:$username---性别:$sex--年龄:$age";
}
  • 案例调用
void main(args) {print(printUserInfo('张三'));print(printUserInfo('张三',age: 20,sex: "女"));//age 和 sex必须传入print(printInfo('张三',age: 22,sex: "女"));
}

15.5 required命名参数

案例:

  • 在定义一个类时,我们想让构造方法中的参数作为必须传入的命名参数时,采用required修饰
//表示 name 和age 是必须传入的命名参数
class Person {String name;int age;Person({required this.name,required this.age});  //表示 name 和age 必须传入String getName() {return "${this.name}---${this.age}";}
}
  • 案例调用
void main(args) {Person p=new Person(name: "张三",age: 20);print(p.getName());
}

15.6 required命名参数可选

  • 在定义一个类,构造函数中的参数,我们想让一部分可以传入也可以不传入,另一部分必须传入,采用可控类型修饰.

案例:

  • name可以传入也可以不传入,age必须传入
class Person {String? name;//可空属性int age;Person({this.name, required this.age});//表示name可空,age必须传入.String getName(){return "${this.name} --- ${this.age}";    }
}
  • 案例调用
void main(args) {Person p=new Person(name: "张三",age: 20);print(p.getName());  //张三---20Person p1=new Person(    age: 20);print(p1.getName());  //null---20
}

15.7 总结

  1. null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能。
  • ? 可空类型(相当于Swfit中的可选值Optional)
  1. ! 类型断言(相当于Swift中的强制解包)
  2. late关键字主要用于延迟初始化.声明构造方法时,要求初始化成员不能为空,于是得加上late懒加载修饰.
  3. required关键词
  • 最开始@required是注解; 现在它已经作为内置修饰符
  • 主要用于允许根据需要标记任何命名参数(函数和类),使得它们不为空.因为可选参数中必须有个 required参数或者该参数有个默认值.
  1. 在定义一个类,构造函数中的参数,我们想让一部分可以传入也可以不传入,另一部分必须传入,采用可控类型修饰.

十六、Dart性能优化之常量、identical函数、常量构造函数详解

16.1 final和const修饰符

Dart常量用: final和const修饰符修饰.

  • const声明的常量是在编译时确定的,永远不会改变.
  • final声明的常量允许声明后再赋值,赋值后不可改变,final声明的变量是在运行时确定的.
  • final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化.

final和const区别:

  • final可以开始不赋值,只能赋一次;而final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化.
//const常量
const PI=3.14;
//PI=3.14159;  //const定义的常量没法改变
print(PI);
// final 常量
final a;a = 13;
//  a=14; //不能再重新赋值print(a);final d = new DateTime.now();print(d);//2023-05-01 14:16:39.145643

16.2 Dart中const identical函数

dart:core 库中identical函数的用法介绍

  • 用法:
bool identical(Object? a,Object? b
)
  • 检查两个引用是否指向同一个对象
var o = new Object();
var isIdentical = identical(o,new Object());//false, different objects
print(isIdentical);
isIdentical = identical(o,o);// true , same object
print(isIdentical);
isIdentical = identical(const Object(),const Object());//true, const canonicalizes 规范化
print(isIdentical);
isIdentical = identical([1], [1]); // false
print(isIdentical);
isIdentical = identical(const [1], const [1]); // true
print(isIdentical);
isIdentical = identical(const [1], const [2]); // false
print(isIdentical);
isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
print(isIdentical);

案例1: identical对两个对象的引用检查

  var o1 = new Object();var o2 = new Object();print(identical(o1,o2));  //false  不共享存储空间print(identical(o1,o1));   //true 共享存储空间

案例2: 采用const修饰的常量构造函数通过identical引用检查

  //const Object()表示实例化常量构造函数//o1 和 o2共享了存储空间var o1 = const Object();var o2 = const Object();print(identical(o1,o2));  //true 共享存储空间print(identical(o1,o1));  //true 共享存储空间

案例3: 两个相同的List列表

  var a=[2];var b=[2];print(identical(a,b)); //false 不共享存储空间

案例4: const修饰的两个相同元素的List列表

print(identical(const [2],const [2])); //true
const a=[2];
const b=[2];
print(identical(a,b)); //true 共享存储空间

案例5: const修饰的两个不同元素的List列表

  const c=[2];const d=[3];print(identical(c,d)); //false  不共享存储空间
  • 因此: const关键词在多个地方创建相同的对象的时候,内存中只保留了一个对象
  • 共享存储空间条件: 1、常量 2、值相等.

16.3 Dart普通构造函数

案例:

class Container{int width;int height;Container({required this.width,required this.height});
}
void main(){var c1 = new Container(width: 100, height: 100);var c2 = new Container(width: 100, height: 100);print(identical(c1,c2));//false, c1和c2在内存中存储了2份
}

16.4 常量构造函数

常量构造函数总结如下:

  1. 常量构造函数需以const关键字修饰
  2. const构造函数必须用于成员变量都是final的类
  3. 如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
  4. 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象.
  5. Flutter中const修饰不仅仅是节省组件构建时的内存开销,Flutter在需要重新构建组件的时候,由于这个组件不应该改变的,重新构建没有任何意义,因此Flutter不会重新构建const组件.

案例: 常量构造函数

class Container {final int width;final int height;const Container({required this.width,required this.height});
}
  • 案例调用
var c1 = Container(width: 100, height: 100);
var c2 = Container(width: 100, height: 100);
print(identical(c1,c2));//false
var c3 = const Container(width:100,height:100);
var c4 = const Container(width:100,height:100);
print(identical(c3,c4));//true
var c5 = const Container(width:100,height:100);
var c6 = const Container(width:100,height:100);
print(identical(c5,c6));//false
  • 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象.

16.5 总结

  1. Dart常量用: final和const修饰符修饰.
  • const声明的常量是在编译时确定的,永远不会改变.
  • final声明的常量允许声明后再赋值,赋值后不可改变,final声明的变量是在运行时确定的.
  • final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化.
  1. final和const区别:
  • final可以开始不赋值,只能赋一次;而final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化.
  1. identical: 检查两个引用是否指向同一个对象
  2. 常量构造函数总结如下:
  • 常量构造函数需以const关键字修饰
  • const构造函数必须用于成员变量都是final的类
  • 如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
  • 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象.
  • Flutter中const修饰不仅仅是节省组件构建时的内存开销,Flutter在需要重新构建组件的时候,由于这个组件不应该改变的,重新构建没有任何意义,因此Flutter不会重新构建const组件.
  1. 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象.

http://www.ppmy.cn/news/60387.html

相关文章

算法 DAY45 动态规划07 70. 爬楼梯 322. 零钱兑换 279. 完全平方数 139. 单词拆分 多重背包

70. 爬楼梯 和377. 组合总和 Ⅳ (opens new window)基本就是一道题了。本题代码不长&#xff0c;题目也很普通&#xff0c;但稍稍一进阶就可以考察完全背包 class Solution { public:int climbStairs(int n) {vector<int> nums {1,2};vector<int> dp(n1,0);dp[0…

使用@Autowired、@Qualifier、@Primary注解自动装配组件

1.Autowired、Qualifier、Primary注解 1.1.Autowired注解 Autowired注解可以对类成员变量、方法和构造函数进行标注&#xff0c;完成自动装配的工作。 package org.springframework.beans.factory.annotation;import java.lang.annotation.Documented; import java.lang.ann…

计算卸载论文阅读01-理论梳理

标题&#xff1a;When Learning Joins Edge: Real-time Proportional Computation Offloading via Deep Reinforcement Learning 会议&#xff1a;ICPADS 2019 一、梳理 问题&#xff1a;在任务进行卸载时&#xff0c;往往忽略了任务的特定的卸载比例。 模型&#xff1a;针…

Zero系列三部曲:Zero、Zero-Offload、Zero-Infinity

Zero系列三部曲&#xff1a;Zero、Zero-Offload、Zero-Infinity ZeroIntroductionZero DP流程图详解 Zero-R Zero-OffloadZero- Infinityreference Zero Introduction 以数据并行为例&#xff0c;在训练的时候&#xff0c;首先把模型参数在每个GPU上复制一份&#xff0c;然后…

【微信小程序开发】【SpringBoot】解决真机调试中无法向后台请求数据的问题

前言 最近做了一个微信小程序SpringBoot的一个项目&#xff0c;在编译器中用localhost请求后台可以实现&#xff0c;但是在手机上进行真机调试就无法正确的从后台请求数据&#xff0c;问题已经解决&#xff0c;下面是我的一点经验 获取本机的ip地址&#xff08;ipv4&#xff09…

一个简单程序JSP+Mysql/ServletAPI+MySQL(servlet获取请求的json数据)

一个简单程序包括两种请求方式 1、JSP+Mysql(JSP获取sql语句对数据库进行查询) 2、ServletAPI+MySQL(servlet获取请求的json数据中的sql语句对数据库进行查询并响应返回) 1. 创建项目 使用 IDEA 创建一个 Maven 项目. 1.1、File -> New Project Name:javaservlet6 Lo…

简单有趣的轻量级网络 Efficientnet(网络结构详解+详细注释代码+核心思想讲解)——pytorch实现

这期博客我们来学习一下Efficientnet网络,属于NAS系列中最优秀的轻量级网络之一,通过NAS搜索的方式确定最佳的网络结构。之前的神经网络的宽度深度,输入图像的分辨率,是怎么获得的呢,说白了就是经验,研究人员通过无数的设计经验获得的,但是网络的发展不可能一直通过经验…

flask+opencv+实时滤镜(原图、黑白、怀旧、素描)

简介&#xff1a;滤镜&#xff0c;主要是用来实现图像的各种特殊效果。图像滤镜用于改变图像的视觉效果&#xff0c;使其具有特定的风格。下面是这三种滤镜的详细说明&#xff1a; 1、黑白&#xff08;Grayscale&#xff09;&#xff1a;黑白滤镜将彩色图像转换为灰度图像&…