Home > Back-end >  Specify callback function in dart/flutter that accepts two possible sets of parameters
Specify callback function in dart/flutter that accepts two possible sets of parameters

Time:09-13

Is there a way to create a callback function that accepts one of two different sets of parameters? Or have two separate callback functions as options, and make sure at least one of them is specified?

I have a view that I want to pass a callback function, that either includes a Goal or a title and description (which would end up being put together into a goal).

void Function({required String title, String? description}) onGoalPopupCompletionWithString;

void Function({required Goal goal}) onGoalPopupCompletionWithGoal;

I want one, but not both of these callbacks to be required - if there is a function with a goal as a parameter, I'd execute that, but if not, I'd execute the one with a String title and a String description. Something like this:

if (onGoalPopupCompletionWithGoal != null) {
    // execute this callback function
} else {
    // execute onGoalPopupCompletionWithString
}

CodePudding user response:

That's not something which can be expressed in the Dart type system.

A single function which can be called as void Function({required String title, String? description}) or void Function({required Goal goal}) will have a signature of:

  void Function({String title, String? description, Goal goal})

Any implementation of that type will either have to make title and goal optional, or provide them with default values. In either case, there is no way, in the type system, to ensure that the function is always invoked as one of the original types.

Also, it'll be highly annoying to write, you'd probably be better off with two different callbacks.

You can provide two callback parameters, one of each kind, and require that at least one of them is required ... but not in the type system. You'd have to make both optional, and check at runtime that at least one was provided.

Having as single parameter which accepts either function type, that requires a union type. A union type allows either one type or another, in this case either void Function({required String title, String? description}) or void Function({required Goal goal}). Dart does not have union types in general.

If you need to pass both of these types through the same currently valid Dart type, the type needs to be a supertype of both. The closest common supertype of those two types is Function.

(The only function types that void Function({required Goal goal}) can be assigned to are void Function({required X goal}) where X is a subtype of Goal. I guess you can also change the void to another, equivalent, top-type. Any other function type allows its functions to be called in a way that void Function({required Goal goal}) does not.)

Dart does have one kind of type union: Classes with subclasses. You can declare a callback class:

abstract class MyCallback {
}
class TitleCallback extends Callback {
  final void Function({required String title, String? description}) callback;
  TitleCallback(this.callback);
}  
class GoalCallback extends Callback {
  final void Function({required Goal goal}) callback;
  GoalCallback(this.callback);
}  

Then you can require one such callback, and dispatch on it as necessary.

  • Related