Dart/Flutter 中的 myFunction、myFunction() 和 myFunction.call() 之间的区别

Difference between myFunction, myFunction(), and myFunction.call() in Dart/Flutter

我注意到当我有一个将函数作为参数的 widget/class 时,当需要调用这些函数时,可以通过以下三种方式之一(据我所知):

(考虑一个函数,myFunction)

  1. 我的函数

  2. 我的函数()

  3. myFunction.call()

但奇怪的是,我注意到当使用选项 1) 时,它将(仅有时)不起作用并且需要使用选项 2 或 3 才能工作。

这是为什么?

具体示例(我在parent中用打印调试验证了不一致的调用行为):

class SoundPickerTile extends StatelessWidget {
  final Sound sound;
  final Function() checkboxCallback;
  final Function() soundPlayCallback;

  SoundPickerTile(
      {required this.sound, required this.checkboxCallback, required this.soundPlayCallback});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: checkboxCallback, // <--------------- Function executes in parent
      child: Container(
        color: sound.isIncluded ? Colors.lightGreen.withAlpha(100) : Colors.white,
        child: Padding(
          padding: EdgeInsets.fromLTRB(20, 10, 0, 10),
          child: Row(
            children: [
              Expanded(
                child: Text(
                  sound.shortTitle,
                ),
              ),
              Expanded(
                child: IconButton(
                  icon: Icon(Icons.play_circle_outline),
                  onPressed: () {
                    print("this line of code was reached"); // this works
                    soundPlayCallback; // <--------------- Function *does not* execute in parent
                  },
                ),
              ),

            ],
          ),
        ),
      ),
    );
  }
}

GestureDetector中我们使用:

onTap: checkboxCallback, 

没有 (),因为那会立即调用函数 ,我们不想调用函数,我们只想传递一个 [=31] =]参考函数 onTap被调用时应该发生什么。

然后:

onPressed: () {
                    print("this line of code was reached"); // this works
                    soundPlayCallback; // <--------------- Function *does not* execute in parent
                  },

因为我们没有使用 () 它没有被 调用 它只是一个 reference 函数。 相反,您可以做的是: onPressed: soundPlayCallback; 或者添加 ()

编辑.

它们都是同一个对象,但有两种不同的行为。

myFunction 是您的函数,但形状像一个对象。因此,您可以将其作为 onTap 的参数传递(它采用类似的函数作为参数)。这也是为什么它在父级中是 运行 的原因,这就是它应该如何工作的原因。它作为一个对象被抛来抛去,父级对其调用 ()。

它没有在下面执行的原因是因为您只是简单地将函数作为一个对象放置下来。就像您之前将它作为对象传递一样,现在您只是说嘿,这是函数,但我不会用它做任何事情。

我的函数; -> 没有 ()

因此,为了使其正常工作,您需要使用数字 2. 或 3.

myFunction() -> 这将调用您的对象(您的函数)和 运行 它的代码,这与前面提到的您只是放下对象的示例相反。 () 很重要!

现在 2. 和 3. 之间的区别是..几乎没有!

() 实际上在后台执行 .call(),但是如果您有一个可能为 null 的 myFunction,那么您可以这样做:

myFunction?.call();

只有当函数不为 null 时才会调用该函数,否则它不会执行任何操作。

希望这很清楚,在指定回调时也尝试定义一个 return 值,这将使您更快地理解传递函数。看看 typedef,它们基本上是特定函数的签名(例如 VoidCallback)。一旦掌握了传递函数的概念,就会变得轻而易举!祝你好运。

让我们检查这些案例并了解它们是什么:

  1. myFunction:

这只是对函数的引用。当您编写此代码时,不会调用该函数。相反,我们可能会将该功能提供给其他人,他们将来可能会调用它,也可能不会。

  1. myFunction()
  2. myFunction.call():

调用函数。当您编写此代码时,该函数将执行,无论它发生了什么副作用,它 returns 无论它 returns.

所以2和3完全一样。那么我们重点说说1和2的区别,也就是myFunctionmyFunction().

myFunction 是对函数的引用。有点像 int i = 5 中的 i。您可以通过在末尾添加 () 来调用它,或者调用它的 .call() 方法。同样,你可以用 i.

i.isEven

示例:我正在调用函数。无论它有什么副作用都会在下一行之前发生。

myFunction(); 
myFunction.call(); // same thing

除了调用 myFunction,您还可以将其作为函数的引用传递。这就像传递一个 int。您正在将对此函数的引用传递到代码中的其他地方。将来可能会或可能不会被调用。你可以调用它,你可以把它扔掉,这是你的决定。

示例:亲爱的按钮,这是一个函数。按下时调用它。

Button(
  onPressed: myFunction, 
)

示例:亲爱的按钮,这里有一个 return 引用 myFunction 的小函数(() =>)。当按钮调用它时,它会收到对 myFunction 的引用。但是,该按钮只是调用您提供给 onPressed 的内容。它不关心你 return 从中得到什么。因此,您 return 引用 myFunction 但它从未被调用,它被丢弃了。

Button(
  onPressed: () => myFunction,
  onPressed: () {return myFunction;} // same thing
)

示例:亲爱的按钮,这是一个调用 myFunction() 和 return 的小函数,无论它是什么 return。所以 myFunction 实际上是在按下按钮时调用的。

Button(
  onPressed: () => myFunction(),
)

示例:亲爱的按钮,这里有一个没有 return 任何东西的小函数。它的其中一行是 myFunction;,它什么都不做,就像写 1;,什么也没做。因此不调用 myFunction。

Button(
  onPressed: () { myFunction; }
)

myFunction 的任何可能用法都应属于这些类别之一。示例的描述应该有助于理解该用法的含义。