Home > Blockchain >  How to solve this problem: The function can't be unconditionally invoked because it can be 
How to solve this problem: The function can't be unconditionally invoked because it can be 

Time:06-18

void main() {
  myCar mebicar = myCar(parts: tyre);
  mebicar.parts();
}

class myCar {
  myCar({this.parts});

  final Function? parts;
}

void tyre() {
  print("black tyre");
}

CodePudding user response:

Since you have a question mark '?' in final Function? parts;, this method can be null. It is not possible to call a null function. You can fix your code with a check before calling the method:

myCar mebicar = myCar(parts: tyre);
if(mebicar.parts != null){
    mebicar.parts();
}

CodePudding user response:

The error comes from Dart's ability to protect you from potentially nullpointer exceptions. This is done by having the concept of differentiate between nullable and non-nullable types. And when dealing with nullable types, we are enforced by Dart to either handle the case of the value being null, or tell Dart that you know the risk but it is fine.

In your case, you have defined the parts variable to be a nullable type Function? (the question mark tells us it is nullable). So the variable can point to a Function or null.

Dart will then warn us about the risk of the field being potentially null in case we try use the field without ensuring it is safe to use it. There are several ways we can solve this.

We could change the type to Function by requiring a value for the variable when creating the myCar object:

class myCar {
  myCar({required this.parts});

  final Function parts;
}

If we don't want to do any changes to myCar we can either solve it by creating a local variable where we checks for null. This check will end up doing a automatic type promotion of the partsFunctionvariable:

void main() {
  myCar mebicar = myCar(parts: tyre);
  Function? partsFunction = mebicar.parts;

  if (partsFunction != null) {
    partsFunction();
  }
}

Alternative we can do this:

void main() {
  myCar mebicar = myCar(parts: tyre);
  
  if (mebicar.parts != null) {
    mebicar.parts!();
  }
}

Of if you are sure the variable are never null you can also just do:

void main() {
  myCar mebicar = myCar(parts: tyre);
  mebicar.parts!();
}

The point of ! is to tell the Dart compiler that it should just ignore this potential nullpointer exception and instead insert a runtime check which will be checked when running your application. So in case of mebicar.parts being null at runtime, the application would crash.

The reason why if (mebicar.parts != null) does not trigger a automatic type-promotion is that we in Dart have the concept of getter/setter methods that should be able to act as if they are normal variables in a class. So in Dart, we cannot differentiate between a class variable and a class getter/setter.

Since getter/setter are normal methods, they are allowed to return a different result each time they are called. So that means that just because we did a type check with if (mebicar.parts != null), it doesn't mean that the second time we ask for mebicar.parts, that the value are not null.

This is why we can do the type promotion of saving the value into a local variable since we here know for sure that the variable keeps it value between readings as long we have not done any writing to it between the readings.

  •  Tags:  
  • dart
  • Related