当前位置: 首页 > news >正文

Flutter: Dart 参数,以及 @required 与 required

1. Dart 参数

Dart 函数的参数分 3 种类型:

  • 位置参数
  • 命名参数
  • 可选位置参数

1.1 位置参数 (positional parameters)

参数位置重要,名称任意,

// 定义
void debugger(String message, int lineNum) {}

// 调用
debugger('A bug!', 55);

参数不能多,不能少,实参与形参从左到右一一按位置对应,这是最基本的参数。

1.2 命名参数 (named Parameters)

命名参数:一般函数参数个数数量较多,比如有几十个,按位置传递参数的方法容易出错,不现实。此时可使用命名参数。对于命名参数,参数位置无关紧要,名称重要。
定义函数时,将参数放在花括号中,调用时,指定参数名称。

// 定义
void debugger({String message, int lineNum}) {}

// 调用,位置无关紧要,
// 写成 debugger(lineNum: 44, message: 'A bug!'); 也可以
debugger(message: 'A bug!', lineNum: 44);  

命名参数默认可选,如果需要指定要求参数必须提供,可使用 @required 或者 required,具体用哪一个,与 Dart 版本相关。

如果使用 Dart 1.12 及以后的版本,下面的函数,因为变量默认为 sound null safety(可靠的空安全),函数

void debugger({String message}) {}

要么改成

void debugger({required String message}) {}

要么改成

void debugger({String? message}) {}

1.3 可选位置参数 (optional positional parameters)

放在中括号中的参数是可选位置参数,例如,以下代码中的参数 z

int addSomeNums(int x, int y, [int z]) {
  int sum = x + y;
  if (z != null) {
    sum += z;
  }
  return sum;
}

addSomeNums(5, 4); // okay, because the third parameter z is optional 
addSomeNums(5, 4, 3); // also okay

可选位置参数可以指定默认值:

// function signature 
int addSomeNums(int x, int y, [int z = 5]) => x + y + z;

// calling that function without passing in the third argument
int sum = addSomeNums(5, 6);
assert(sum == 16); // 5 + 6 + 5

// calling that function with passing in the third argument
int sum2 = addSomeNums(5, 6, 10);
assert(sum2 == 21); // 5 + 6 + 10

方括号 [ ] 中的所有参数全部可选, 也就是说,它们必须为 nullable,对于 Dart 1.12 及以后的版本,可以在参数类型后加?,允许其值为 nullDart 1.11 及之前的版本不需要加。

void optionalThreeGreeting(int numberOfTimes,
    [String? name1, String? name2, String? name3]) {
}

1.4 参数组合形式

  • 位置参数
  • 命名参数
  • 可选位置参数
  • 位置参数 + 命名参数
// ✅
String greeting(String name, {String? message}) { ... }
  • 位置参数 + 可选位置参数
// ✅
void hide(bool hidden, [bool? animated]) { ... }

不能混合命名参数与可选位置参数:

// ❌
int mixedSum({required int a, int? b}, [int? c]) { ... }

2. @requiredrequired 的区别


As of Dart 2.12, the required keyword replaces the @required meta annotation. For detailed info look into the official FAQ. The following answer has been updated to reflect both this and null safety.

@required is just an annotation that allows analyzers let you know that you’re missing a named parameter and that’s it. so you can still compile the application and possibly get an exception if this named param was not passed.
However sound null-safety was added to dart, and required is now a keyword that needs to be passed to a named parameter so that it doesn’t let the compiler run if this parameter has not been passed. It makes your code more strict and safe.
If you truly think this variable can be null then you would change the type by adding a ? after it so that the required keyword is not needed, or you can add a default value to the parameter.


Dart 1.12 版开始,使用关键字 required 取代 @required 标记 (同时预设开启sound null safety, 没有特别说明的type 都是 non-nullable 的。)

void debugger({String message, int lineNum}) {}

命名参数默认可选,但是如果要求调用此函数时必须提供哪些参数,对于 Dart 1.12 之前的版本,使用 @required annotation,对于 Dart 1.12 以及之后的版本,使用 required keyword

以下是一个 Flutter project, 设置 pubspec.yaml 中的 Dart 版本:

environment:
  sdk: ">=2.11.0 <3.0.0"

测试函数 func

class _MyHomePageState extends State<MyHomePage> {

  // function for test
  void func({ String arg1,  int arg2}) {
    print(arg1);
    print(arg2);
  }

  
  Widget build(BuildContext context) {
  	// Ok,compile pass
  	// 使用 @required 标记, 分析器会指出命名参数丢失,
  	// 但对实际编译运行没有影响。
    func(); 
    
    return Scaffold(
      appBar: AppBar(
        title: const Text("title"),
      ),
      body: const Center(child: Text('body')),
    );
  }
}

如果改为使用 Dart 2.12,同时 @required 改为 required,此时如果丢失参数,将无法通过编译。

所以,required 作为关键字强制要求提供参数@required 只是一种标记required 强于 @required

environment:
  sdk: ">=2.17.6 <3.0.0"
class _MyHomePageState extends State<MyHomePage> {
  void func({required String arg1, required int arg2}) {
    print(arg1);
    print(arg2);
  }

  
  Widget build(BuildContext context) {
  
	// 无法通过编译 !!!
	// Error: Required named parameter 'arg1' must be provided.
    func();

    return Scaffold(
      appBar: AppBar(
        title: const Text("title"),
      ),
      body: const Center(child: Text('body')),
    );
  }
}

  1. https://flutterbyexample.com/lesson/function-arguments-default-optional-named
  2. https://ithelp.ithome.com.tw/articles/10271892?sc=hot
  3. https://stackoverflow.com/questions/54181838/flutter-required-keyword
  4. https://stackoverflow.com/questions/67642000/what-is-the-difference-between-required-and-required-in-flutter-what-is-the-di
  5. https://stackoverflow.com/questions/64621051/how-to-enable-null-safety-in-flutter
  6. https://sarunw.com/posts/dart-parameters/#how-to-declare-parameters-in-dart

相关文章:

  • 基于JAVA网上商城系统演示录像计算机毕业设计源码+数据库+lw文档+系统+部署
  • 【复杂网络】关于复杂网络中的动力学系统重构的文献资料整理
  • 应对数据安全典型薄弱点,这家医院“外防内控”筑牢屏障
  • 嵌入式开发:注释C代码的10个技巧
  • Qt5开发从入门到精通——第九篇一节( Qt5 文件及磁盘处理—— 读写文本文件)
  • ⌈Linux_ 感受系统美学⌋ 抛开图形化界面,深入探索命令行操作系统
  • 09-28 周三 使用朴素贝叶斯进行垃圾邮件处理
  • python+cuda编程(二)
  • 攻防世界-filemanager
  • 软件项目管理简答题
  • Spring源码分析(二):底层架构核心概念解析
  • vue3 watch的各种使用情景
  • Dubbo(二)
  • Qt6.3.2下QChart的使用
  • GAM注意力机制
  • 【RocksDB】TransactionDB源码分析
  • 08.Android之View事件问题
  • 78. Subsets
  • CAP 一致性协议及应用解析
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • ES6系统学习----从Apollo Client看解构赋值
  • exports和module.exports
  • gcc介绍及安装
  • Java 23种设计模式 之单例模式 7种实现方式
  • mysql innodb 索引使用指南
  • Next.js之基础概念(二)
  • rabbitmq延迟消息示例
  • Web Storage相关
  • 初识 webpack
  • 搭建gitbook 和 访问权限认证
  • 开源地图数据可视化库——mapnik
  • 区块链分支循环
  • 说说动画卡顿的解决方案
  • 提醒我喝水chrome插件开发指南
  • 想写好前端,先练好内功
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #{} 和 ${}区别
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (12)Hive调优——count distinct去重优化
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (二)c52学习之旅-简单了解单片机
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (全注解开发)学习Spring-MVC的第三天
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • (转)人的集合论——移山之道
  • ../depcomp: line 571: exec: g++: not found
  • .NET Core WebAPI中封装Swagger配置
  • .NET Core中Emit的使用
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .Net Remoting常用部署结构