dart中将方法当做参数传递时的注意事项

简介: 众所周知,Dart是一门面向对象的语言,比Java更纯粹,Dart中的方法也是对象,也有类型Function。这意味着方法可以被分配给对象,也可以当做参数传递给其他方法。

dart中将方法当做参数传递时的注意事项

众所周知,Dart是一门面向对象的语言,比Java更纯粹,Dart中的方法也是对象,也有类型Function。这意味着方法可以被分配给对象,也可以当做参数传递给其他方法。

方法当做参数传递给另一个方法

这里我们先定义一个返回值为void,入参为一个int的printElement方法,它的作用很简单,就是打印这个int值。

接着我们初始化一个数组,然后将printElement方法当做参数传递给我们的list.forEach方法,这样我们将list中的每个元素,依次交给printElement方法去打印。

void printElement(int element) {
  print(element);
}

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

  // Pass printElement as a parameter.
  list.forEach(printElement);
}

如果不太好理解的话,可以看下list.forEach方法源码,也就是Iterator#forEach(),如下所示。

  /**
   * Applies the function [f] to each element of this collection in iteration
   * order.
   */
  void forEach(void f(E element)) {
    for (E element in this) f(element);
  }

可以看出,我们的forEach方法接受的参数是一个方法,该方法的返回值void,一个入参f,入参类型这里用的是泛型。

方法内部调用了for循环,依次获取到Iterator(也就是我们的List)中的元素element,然后将element作为参数传递给f方法,同时调用这个f方法。这个f方法就是我们之前传入的printElement方法。

重要细节

接下来我们重点说下几个细节。

1、第一个细节,就是方法当做参数传递的时候,只需要传递方法名即可,不需要带上方法的括号。具体请看我们的printElement方法是如何定义,以及是如何传递给list.forEach方法的。

2、方法作为参数的时候传递给其他方法的时候,不会立即执行。

方法当做参数传递的时候,方法名表示该方法的引用,这个引用当做参数传递的时候不会立即执行,只会再调用的时候执行。

3、入参方法在被实际调用时,会添加括号,当做正常的方法调用。

具体请看printElement方法当做参数传递给list.forEach方法的过程,以及list.forEach方法内部是如何调用入参方法f的。

方法当做参数传递时,无括号和有括号的区别

这里之所以一再强调方法调用有没有括号,是因为我在这里吃过亏,另一方面对这些细节理解到位有助于我们加深对Dart语言的理解。

我们看个例子就明白了。

这里我们定义一个add方法,返回值为int,入参为两个int。

然后定义一个test方法,返回值为int,前两个入参都是int类型,第三个参数是Function类型。

然后在main方法中,将add方法作为参数传递给test方法,并打印test方法的执行结果。

int add(int a, int b) {
  return a + b;
}

int test(int a, int b, Function operation) {
  return operation(a, b);
}

main() {
  print(test(5, 2, add));
}

这里add方法当做参数传递时值传递了方法名add,没有括号也没有参数,一起跟预期一样。

接下来我们修改下main方法中的测试方法,我们第三个参数修改为add(1,1),代码如下所示:

main() {
  print(test(5, 2, add(1,1)));
}

具体错误提示如下:

提示的意思是说,int类型的参数不能赋值给Function类型的参数,也就是我们的add(1,1)结果为int,跟test方法中定义的第三个入参的类型不匹配。

好了,我们应该已经看到方法名(不带括号)和方法执行语句(带括号)的区别了。

结论如下:

  • 方法名(不带括号)作为参数传递给其他方法时,传递的是方法的引用,该方法不会立即执行。
  • 方法执行语句(带括号)作为参数传递给其他方法时,该方法会立即执行,我们传递过去的是方法的返回值。

在java中,方法不是对象,所以我们不会遇到将方法当做参数传递给其他方法这种情况。我们经常使用的事直接将方法执行语句(也就是它们的返回值)作为参数直接传递。

最后,Flutter和Dart语言的很多思想和语法,都是参考或照搬的前端,如果学习或开发中遇到困惑,那么从前端查起应该会容易好多。

参考

Dart-Functions

javascript函数(二)--将函数作为参数传递

In dart , What does passing a function or a class without "()" parenthesis does?

tear-off

Lint rules: unnecessary_lambdas

相关文章
|
9月前
|
存储 C语言
C 语言函数完全指南:创建、调用、参数传递、返回值解析
函数是一段代码块,只有在被调用时才会运行。 您可以将数据(称为参数)传递给函数。 函数用于执行某些操作,它们对于重用代码很重要:定义一次代码,并多次使用。
250 3
|
JSON 前端开发 数据格式
四种常见的参数传递方式
四种参数传递方式
215 0
|
8月前
|
缓存 监控 程序员
Python中的装饰器是一种特殊类型的声明,它允许程序员在不修改原有函数或类代码的基础上,通过在函数定义前添加额外的逻辑来增强或修改其行为。
【6月更文挑战第30天】Python装饰器是无侵入性地增强函数行为的工具,它们是接收函数并返回新函数的可调用对象。通过`@decorator`语法,可以在不修改原函数代码的情况下,添加如日志、性能监控等功能。装饰器促进代码复用、模块化,并保持源代码整洁。例如,`timer_decorator`能测量函数运行时间,展示其灵活性。
64 0
|
6月前
|
Python
Python变量的作用域_参数类型_传递过程内存分析
理解Python中的变量作用域、参数类型和参数传递过程,对于编写高效和健壮的代码至关重要。正确的应用这些概念,有助于避免程序中的错误和内存泄漏。通过实践和经验积累,可以更好地理解Python的内存模型,并编写出更优质的代码。
52 2
|
9月前
|
存储 Java
Java数组与带参数方法:定义、调用及实践
Java数组与带参数方法:定义、调用及实践
92 1
|
9月前
|
JavaScript 前端开发
js函数:函数是JS的基本组成单元,用于封装代码块以实现特定功能。理解函数的定义、调用和参数传递方式非常重要。具体案例详解
js函数:函数是JS的基本组成单元,用于封装代码块以实现特定功能。理解函数的定义、调用和参数传递方式非常重要。具体案例详解
72 1
|
自然语言处理 Dart 算法
[Flutter]足够入门的Dart语言系列之函数:匿名函数、作用域闭包、类型别名和内联函数类型
函数在Dart中是对象,因此,可以将函数作为参数传递给另一个函数、作为一个'值'赋值给一个变量。下面主要介绍匿名函数、内联函数类型的使用,以及了解下作用域和闭包...
805 0
[Flutter]足够入门的Dart语言系列之函数:匿名函数、作用域闭包、类型别名和内联函数类型
|
C++ 编译器 安全
方法参数传递案例
方法参数传递案例
104 0
方法参数传递案例
|
编译器 C++
C++函数参数传递的三种方式
C++函数参数传递的三种方式
208 0