Reputation: 4404
I want to implement copyWith()
method for my class. Since its inhirited class, i got error:
The member being overridden.
my basemodel
class BaseData {
int id;
String? createdAt, updatedAt;
BaseData({this.id = 0, this.createdAt, this.updatedAt});
BaseData copyWith({
int? id,
String? createdAt,
String? updatedAt,
}) =>
BaseData(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt);
}
and I have another class that extend to my BaseData
model
class QcData extends BaseData{
String name;
QcData ({this.name =""});
@override
QcData copyWith({
String? name
}){
return QcData(name: name ?? this.name);
}
}
How to create copyWith()
method for my model class?
Thanks in advance.
Upvotes: 4
Views: 3039
Reputation: 17724
Here's a pattern I came up with that seems to work pretty well:
class BaseData {
final int baseValue;
BaseData([Map map = const {}, BaseData? data]) :
baseValue = map['baseValue'] ?? data?.baseValue ?? 0;
T copyWith<T extends BaseData>(Map map) {
return BaseData(map, this) as T;
}
}
class ExtendedData extends BaseData {
final int extendedValue;
ExtendedData([super.map, ExtendedData? super.data]) :
extendedValue = map['extendedValue'] ?? data?.extendedValue ?? 0;
@override
T copyWith<T extends BaseData>(Map map) {
return ExtendedData(map, this) as T;
}
}
One thing to notice with the above however is that since we assign to a member using the construct map[key] ?? defaultValue
we can't easily clear a value.
So a bit of additional code I use says, "if the key exists in map
, unconditionally set its value." This lets us put a key with a null value in the map
parameter dictionary and use that to clear a field.
Updated with this functionality I add the following:
extension MapExtension on Map {
T? valueOf<T>(Object key, [Object? defaultValue]) {
return containsKey(key) ? this[key] : defaultValue;
}
}
Then the constructors change to:
BaseData([Map map = const {}, BaseData? data]) :
baseValue = map.valueOf('baseValue', data?.baseValue ?? 0);
and
ExtendedData([super.map, ExtendedData? super.data]) :
extendedValue = map.valueOf('extendedValue', data?.extendedValue);
Upvotes: 0
Reputation: 63614
We also need to pass data on while creating QcData(child). I prefer modifying constructor this way.
const QcData({
this.name = "",
super.id,
super.createdAt,
super.updatedAt,
});
Now we have access on copyWith method these property, another cause is I like to use const
constructor with final fields.
@override
QcData copyWith({
String? name,
int? id,
String? createdAt,
String? updatedAt,
}) {
return QcData(
name: name ?? this.name,
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
The models will be
class BaseData {
final int id;
final String? createdAt;
final String? updatedAt;
const BaseData({this.id = 0, this.createdAt, this.updatedAt});
BaseData copyWith({
int? id,
String? createdAt,
String? updatedAt,
}) {
return BaseData(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
}
class QcData extends BaseData {
final String name;
const QcData({
this.name = "",
super.id,
super.createdAt,
super.updatedAt,
});
@override
QcData copyWith({
String? name,
int? id,
String? createdAt,
String? updatedAt,
}) {
return QcData(
name: name ?? this.name,
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
}
Upvotes: 3
Reputation: 9166
inheritance means that a class member's definitions should remain the same when you extend, or implement a base class, in your case by doing the:
@override
QcData copyWith({
String? name
}){
return QcData(name: name ?? this.name);
}
this method declaration is not the same as the BaseData
's since they take different sets of arguments, you should remain the arguments the same as the BaseData
, so your code should be this in order to work:
class QcData extends BaseData {
String name;
QcData({this.name = ""});
@override
QcData copyWith({
int? id,
String? createdAt,
String? updatedAt,
}) {
return QcData(name: name ?? this.name);
}
}
Upvotes: 3