How onPressed: func is different from onPressed: () => func() in Dart?

Issue

I have a class:

class Foo {
  void bar() {}
}

And I’m using it like this:

Widget build() {
  late Foo foo;

  return Column(
    children: [
      ElevatedButton(
        onPressed: foo.bar, // Error: 
        child: Text('Use'),
      ),
      ElevatedButton(
        onPressed: () => foo = Foo(), // Assigning foo here
        child: Text('Initialize'),
      ),
    ],
  );
}

The late local variable ‘foo’ is definitely unassigned at this point. (Documentation)

As you can see I’m using the late keyword to give a hint to the analyzer that I’ll be instantiating later, but I still see an error, why?


Note: I’m NOT looking for solutions on HOW to make it work but rather WHY it’s not working?

Solution

Because you are creating the list right away as part of creating the Column object for the children argument. The list contains two ElevatedButton objects which are also created right away as part of creating the list. For creating the first ElevatedButton we provide two arguments, onPressed and child with values which are resolved and send to the ElevatedButton constructor.

The problem is then that to resolve foo.bar it needs get bar from foo. But foo is late and has definitely not been assigned any value at this point since no other code have been running which could provide a value for it.

Notice that when we provide arguments to methods/constructors the values we getting are resolved before we run code inside the method/constructor. Also, we are getting a copy of the reference, so foo.bar needs to be resolved to some value since we cannot use this as some kind of pointer to the foo variable inside build() and later check if it is set to a value inside the ElevatedButton object.

Answered By – julemand101

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *