Reputation: 841
I am using the following plugin: https://pub.dev/packages/freezed
I want to subclass a freezed data class to provide additional functionality in my data layer. So I have my data class which looks like:
import 'dart:ui';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'card.freezed.dart';
@freezed
abstract class Card with _$Card {
factory Card({String text, Color color, List<String> categories}) = _Card;
}
Now I want to have this Card class as a super class to my CardModel so that the CardModel has access to the same fields, the copyWith method, value equality, ... But I have no Idea how to go about this. I am trying something like this:
import 'package:flutter/widgets.dart';
import 'package:growthdeck/features/card_deck/domain/entities/card.dart';
import '../../domain/entities/card.dart';
abstract class CardModel extends Card {
factory CardModel.fromMap(Map<String, dynamic> card) => Card(
text: card["text"],
color: Color(int.parse(card['color'])),
categories: card['categories'] as List<String>,
);
}
Which throws the following error:
package:growthdeck/features/card_deck/data/models/card_model.dart 11:9 new CardModel.fromMap
test/features/card_deck/data/models/card_model_test.dart 13:23 main.<fn>
type '_$_Card' is not a subtype of type 'CardModel' in type cast
Is there any way to do this properly? My workaround would be to simply "wrap" the Card class inside the CardModel and provide a toCard() method which is not very elegant :S
Upvotes: 23
Views: 19988
Reputation: 8711
Freezed 3.0 will support inheritance:
class Base {
Base(String value);
}
@freezed
class Usual extends Base with _$Usual {
Usual({int? a}) a = a ?? 0, super('value');
final int a;
}
Upvotes: 0
Reputation: 1160
Freezed uses sealed
classes to model inheritance, if you have a closed set of subclasses (cmp. this section).
I'm not sure how one can add methods to those subclasses, but in your case, a subclass with just a static
/factory
method wouldn't make much sense anyway.
This should do it:
import 'dart:ui';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'card.freezed.dart';
@freezed
sealed class Card with _$Card {
const factory Card.model({
required String text,
required Color color,
required List<String> categories,
}) = CardModel;
factory Card.fromMap(Map<String, dynamic> card) => CardModel(
text: card["text"],
color: Color(int.parse(card['color'])),
categories: card['categories'] as List<String>,
);
}
or if CardModel
is the only subclass, I would just turn Card
into an interface
and use CardModel
as the freezed
class:
import 'dart:ui';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'card.freezed.dart';
abstract interface class Card {
String get text;
Color get color;
List<String> get categories;
}
@freezed
sealed class CardModel with _$CardModel implements Card {
const factory CardModel({
required String text,
required Color color,
required List<String> categories,
}) = _CardModel;
factory CardModel.fromMap(Map<String, dynamic> card) => CardModel(
text: card["text"],
color: Color(int.parse(card['color'])),
categories: card['categories'] as List<String>,
);
}
Upvotes: 0
Reputation: 2000
Unfortunately, the extends
keyword is forbidden for freezed
generated classes.
However, you can achieve something which resembles the inheritance hierarchy with available Dart tricks:
implements
as last keyword after class declaration like so:class MyModel with _$MyModel implements BaseModel
2.Define your BaseModel
class:
abstract class BaseModel {
// an abstract method
String callMe(final int value);
// an abstract getter
FilePath get useMe;
}
extension BaseModelExtensions on BaseModel {
String callSharedBehaviourAndReuseMeInChildFreezedClasses(int parameter) {
// your logic
return "";
}
}
Upvotes: 1
Reputation: 24197
Morphy supports inheritance https://pub.dev/packages/morphy as well as clean minimal class definitions.
@morphy
abstract class $Pet {
String get name;
int get age;
}
@morphy
abstract class $Cat implements $Pet {
double get whiskerLength;
}
@morphy
abstract class $Dog implements $Pet {
String get woofSound;
}
It also supports polymorphic copy with and to / from json.
main(){
//alter common properties of different sub types
var petsOlder = catsAndDogs.map((pet) => //
pet.copyWith_Pet(age: Opt(pet.age + 1)));
//convert different sub types to json
var json = pets.map((pet) => pet.toJson_2()).toList();
//convert json into different subtypes
var catsAndDogs = json2.map((json) => Pet.fromJson(json)).toList();
}
(I am the developer of the package)
Upvotes: 6
Reputation: 659
Freezed class subclass itself. You dont need to abstract it.
import 'dart:ui';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'card.freezed.dart';
@freezed
class Card with _$Card {
const factory Card.cardModel({String text, Color color, List<String> categories}) = _$CardModel;
}
Run build runner for above freeze will create
abstract class _$CardModel implements Card{}
which you can access by Card factory.
Upvotes: 0
Reputation: 684
Freezed doesn’t support inheritance at the moment so it’s recommended to use composition instead of inheritance as mentioned by the creator here:
https://github.com/rrousselGit/freezed/issues/464
And in the comments of the post.
Upvotes: 14