Rick
Rick

Reputation: 2271

How to implement interface in-line instead of using a class in Dart/Flutter?

Is there any way to implement an interface in dart/flutter without having to use a class?

Currently, how I implement it is with the code below

class _UserSignupInterface extends _SignupSelectUsernamePageState
    implements UserSignupInterface {
  @override
  void onSuccess() {
    _navigateToUserPage();
  }

  @override
  void onError() {
    setState(() {
      _isSignupClickable = true;
    });
  }
}

_attemptSignup() {
  UserSingleton userSingletonInstance = UserSingleton().getInstance();
  UserSignupInterface _userSignupInterface = _UserSignupInterface();

  UserSingleton().getInstance().user.username = _username;

  UserLoginController.attemptSignup(_userSignupInterface,
      userSingletonInstance.user, userSingletonInstance.userDetail, _groupID);
}

However, I would like to implement these interface methods without having to use a class, just as I would in java. Something that would look like the code below.

UserController.attemptSignup(context, new UserSignupRequest() {
            @Override
            public void onSuccess(User user, UserDetail userDetail, Group group) {
                btnContinueWithFacebook.setEnabled(true);
                Intent intent = new Intent(context, ScoopActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

                progressBar.setVisibility(View.GONE);
                startActivity(intent);
            }

            @Override
            public void onFail() {
                Log.d(APP.TAG, "Signup request has failed");
                btnContinueWithFacebook.setEnabled(true);
                progressBar.setVisibility(View.GONE);
                /**
                 * TODO:: Notify user of signup attempt failure
                 */
            }
        }, user, userDetail, group_id);

Upvotes: 4

Views: 7402

Answers (3)

Giddy Naya
Giddy Naya

Reputation: 4658

I know this question already has an answer but I would like to add a more neater implementation close to Java inline interface which I normally use.

First, we have the class which acts as our interface:

class HttpRequestCallback {
  /// Called when http request is completed
  final void Function() onCompleted;

  /// Called when http request is successful
  ///  * [message] is a dynamic object returned by the http server response
  final void Function(dynamic message) onSuccess;

  /// Called when http request fail
  ///  * [message] is a dynamic object returned by the http server response
  final void Function(dynamic message) onError;

  HttpRequestCallback(
      {required this.onCompleted,
      required this.onSuccess,
      required this.onError});
}

Secondly, we have a function that expects the interface as parameter:

Future<void> login(LoginModel model, {HttpRequestCallback? callback}) async {
    var response = await httpClient.doPost(app_constants.ApiEndpoints.Login,
        body: model.toJson());
    // Api request completed
    callback?.onCompleted();

    if (response.success) {
      // Api request successful
      callback?.onSuccess(LoginResponseModel.fromJson(
          response.message as Map<String, dynamic>));
    } else {
      // Api request failed
      callback?.onError(response.message);
    }
  }

Finally, we call the function passing our interface as an argument:

...
apiService.login(loginModel,
    callback: HttpRequestCallback(
       onCompleted: () {
        //...
       },
       onSuccess: (message) {
        //...
       },
       onError: (message) {
        //...
       }
    ));
...

Upvotes: 2

kinghomer
kinghomer

Reputation: 3161

I think you are looking for anonymous class in Dart, but it's not supported.

If i understood well what you are trying to do, you can achieve something similar by passing function as parameter in this way:

enum ResultLogin { OK, ERROR }

class Login {
   Function _listener; // generic function

   Login(listener) {
      _listener = listener;
   }

   void run(){
      ResultLogin result = *DO_YOUR_LOGIN_FUNCTION*;
      _listener(result);
   }
}   

class Main {
    void doLogin(){
        Login myLogin = new Login((ResultLogin result){
                switch(result){

                   case OK:
                      print("OK");
                     break;

                   case ERROR:
                      print("ERROR");
                     break;

                   default:
                     break;
                }
            }
        );

    }
}

In this way you can handle your result and refresh some widget state according to your needs.

Upvotes: 0

lrn
lrn

Reputation: 71713

There is no such feature in Dart. In order to implement an interface, you have to declare a class.

The alternatives is to define the API to accept individual functions instead of a single object, or to declare a helper class which takes the behavior of the necessary methods as constructor arguments.

Example:

class _UserSignupInterface extends _SignupSelectUsernamePageState
    implements UserSignupInterface {
  void Function(_UserSingupInterface self) _onSuccess;
  void Function(_UserSingupInterface self) _onError;
  _UserSignupInterface(this._onSuccess, this._onError);

  @override
  void onSuccess() { 
    _onSuccess(this);
  }

  @override
  void onError() {
    _onError(this);
  }
}

Then you can call it as:

... _UserSignupInterface((self) { 
    self._navigateToUserPage();
}, (self) {
  self.setState(() {
    self._isSignupClickable = true;
  });
})

It's not as pretty as Java, admittedly.

Upvotes: 5

Related Questions