Flutter - Error implementing interface with Freezed
Asked Answered
K

3

2

I'm trying to programme to an interface with Freezed. I want to be able to specify all over my app, the type IUserRegistrationEntity;

My interface:

abstract class IUserRegistrationEntity {
  String nickName;
  String email;
  String confirmEmail;
  String password;
  String confirmPassword;
}

My freezed class:

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:vepo/domain/user_registration/i_user_registration_entity.dart';

part 'user_registration_entity.freezed.dart';

@freezed
abstract class UserRegistrationEntity with _$UserRegistrationEntity {
  @Implements(IUserRegistrationEntity)
  factory UserRegistrationEntity(
      {String nickName,
      String email,
      String confirmEmail,
      String password,
      String confirmPassword}) = _UserRegistrationEntity;
}

Getting the error when running the app:

lib/domain/user_registration/user_registration_entity.freezed.dart:165:7: Error: The non-abstract class '_$_UserRegistrationEntity' is missing implementations for these members:
 - IUserRegistrationEntity.confirmEmail
 - IUserRegistrationEntity.confirmPassword
 - IUserRegistrationEntity.email
 - IUserRegistrationEntity.nickName
 - IUserRegistrationEntity.password
Try to either
 - provide an implementation,
 - inherit an implementation from a superclass or mixin,
 - mark the class as abstract, or
 - provide a 'noSuchMethod' implementation.

class _$_UserRegistrationEntity implements _UserRegistrationEntity {
      ^^^^^^^^^^^^^^^^^^^^^^^^^
lib/domain/user_registration/i_user_registration_entity.dart:4:10: Context: 'IUserRegistrationEntity.confirmEmail' is defined here.
  String confirmEmail;

         ^^^^^^^^^^^^
lib/domain/user_registration/i_user_registration_entity.dart:6:10: Context: 'IUserRegistrationEntity.confirmPassword' is defined here.
  String confirmPassword;
         ^^^^^^^^^^^^^^^
lib/domain/user_registration/i_user_registration_entity.dart:3:10: Context: 'IUserRegistrationEntity.email' is defined here.
  String email;
         ^^^^^
lib/domain/user_registration/i_user_registration_entity.dart:2:10: Context: 'IUserRegistrationEntity.nickName' is defined here.
  String nickName;
         ^^^^^^^^

lib/domain/user_registration/i_user_registration_entity.dart:5:10: Context: 'IUserRegistrationEntity.password' is defined here.
  String password;

         ^^^^^^^^

What am I doing wrong?

Edit: Does this quote from the package docs mean it is not possible?.

Note 2: You cannot use @With/@Implements with freezed classes. Freezed classes can neither be extended nor implemented.

Keen to know if people think this is a drawback if so.

Klug answered 12/12, 2020 at 4:6 Comment(2)
Shouldn't there be const before the factory constructor for generated factories?Estrin
@Estrin Yes I think so thanks, however still getting the errorKlug
E
5

I tested out your code and found the problem from the generated file. Thing is, freezed doesn't override setters from the implemented abstract class. So, for your IUserRegistrationEntity, make the parameters as getters. Like so:

abstract class IUserRegistrationEntity {
  String get nickName;
  String get email;
  String get confirmEmail;
  String get password;
  String get confirmPassword;
}
Estrin answered 12/12, 2020 at 8:19 Comment(4)
Thanks this works. I don't suppose you know how to make IUserRegistrationEntity know about the freezed functions such as copyWith? As my interface is not useful without that. I may need to ask another question.Klug
In that case, I'd suggest making another freezed class keeping IUserRegistrationEntity as base. Wait, I'll edit my answer.Estrin
Unfortunately, you can't make IUserRegistrationEntity know about freezed functions. However, you can do what I commented before and use that class. However, the new class would be exactly like UserRegistrationEntity.Estrin
Thank you. I used your solution. I have just built upon it to solve the second problem that I asked you about, so I posted it in another answer in case anyone else is interested in doing something similar.Klug
K
3

I used rkdupr0n's solution. I would just like to say that I also made the IUserRegistrationEntity interface know about the Freezed package's functions so that I could call them when programming to the IUserRegistrationEntity interface. Well, just the ones that I need currently. I will add the rest soon.

Freezed class becomes:

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:vepo/domain/user_registration/i_user_registration_entity.dart';

part 'user_registration_entity.freezed.dart';
part 'user_registration_entity.g.dart';

@freezed
abstract class UserRegistrationEntity with _$UserRegistrationEntity {
  @Implements.fromString(
      'IUserRegistrationEntity<\$UserRegistrationEntityCopyWith<IUserRegistrationEntity>>')
  const factory UserRegistrationEntity(
      {String nickName,
      String email,
      String confirmEmail,
      String password,
      String confirmPassword}) = _IUserRegistrationEntity;

  factory UserRegistrationEntity.fromJson(Map<String, dynamic> json) =>
      _$UserRegistrationEntityFromJson(json);
}

Interface:

abstract class IUserRegistrationEntity<T> extends FreezedClass<T> {
  String get nickName;
  String get email;
  String get confirmEmail;
  String get password;
  String get confirmPassword;
}

abstract class FreezedClass<T> {
  T get copyWith;
  Map<String, dynamic> toJson();
}
Klug answered 12/12, 2020 at 11:3 Comment(0)
D
-1

add private empty constructer code

example if you are are generating a freezed user class

@freezed
abstract class User with _$User {
  const User._(); // add this
}

it would look like that

Duffie answered 6/10, 2021 at 16:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.