I have to sort items of a class created with @freezed
annotation. I have added Comparable interface to the signature. It is causing following compile time exception:
Error (Xcode): lib/models/app_language.freezed.dart:143:7: Error: The
non-abstract class ‘_$_AppLanguage’ is missing implementations for
these members:Could not build the application for the simulator.
// app_language.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'app_language.freezed.dart';
part 'app_language.g.dart';
@freezed
class AppLanguage with _$AppLanguage implements Comparable<AppLanguage> {
const factory AppLanguage({
@Default("en") String id,
String? name,
String? msg,
@Default([0, 0, 0, 0]) List<int> color,
@Default(false) bool rtl,
}) = _AppLanguage;
factory AppLanguage.fromJson(Map<String, dynamic> json) =>
_$AppLanguageFromJson(json);
@override
int compareTo(AppLanguage other) {
if (rtl == other.rtl) {
if (name != null && other.name != null) {
return name!.compareTo(other.name!);
} else if (name == null && other.name == null) {
return 0;
} else if (name != null) {
return 1;
} else {
return -1;
}
} else {
return rtl ? 1 : -1;
}
}
}
pubspec.yaml (snippet)
dependencies:
freezed: ^2.3.2
freezed_annotation: ^2.2.0
dev_dependencies:
build_runner: ^2.3.3
json_serializable: ^6.6.0
usage
// here value is list of AppLanguages and I am returning another sorted list.
return <AppLanguage>[...value]..sort();
How do I resolve compilation error? Any help will be appreciated.
Right now,
I have added separate comparator so that it could work. But having the model class implements the Comparable is desired.
import 'package:freezed_annotation/freezed_annotation.dart';
import '../localization/localization.dart';
part 'app_language.freezed.dart';
part 'app_language.g.dart';
@freezed
class AppLanguage with _$AppLanguage {
const factory AppLanguage({
@Default(localeDefault) String id,
String? name,
String? msg,
@Default([0, 0, 0, 0]) List<int> color,
@Default(false) bool rtl,
}) = _AppLanguage;
factory AppLanguage.fromJson(Map<String, dynamic> json) =>
_$AppLanguageFromJson(json);
// @override
// // ignore: library_private_types_in_public_api
// int compareTo(_$_AppLanguage other) {
// if (rtl == other.rtl) {
// if (name != null && other.name != null) {
// return name!.compareTo(other.name!);
// } else if (name == null && other.name == null) {
// return 0;
// } else if (name != null) {
// return 1;
// } else {
// return -1;
// }
// } else {
// return rtl ? 1 : -1;
// }
// }
}
int appLanguageComparator(AppLanguage a, AppLanguage b) {
if (a.rtl == b.rtl) {
final aName = a.name;
final bName = b.name;
if (aName != null && bName != null) {
return aName.compareTo(bName);
} else if (aName == null && bName == null) {
return 0;
} else if (aName != null) {
return 1;
} else {
return -1;
}
} else {
return a.rtl ? 1 : -1;
}
}
Usage:
return <AppLanguage>[...value]..sort(appLanguageComparator);
2
Answers
For others that will encounter the same issue in the future, in order to add custom methods/getters etc to a
freezed
class you need to provide a empty const constructor. For example:This implementation will throw a compile error and in order to make it work you need to do:
Keep in mind, the constructor must be an empty constructor.
You have to extend the class with
Comparable<AppLanguage>
and should overridecompareTo
with parameter ofAppLanguage
as following