pass different class object to function - flutter

I have multiple class objects and i want to create a standalone function that will take any class object as parameter.
here is my income class
import 'package:finsec/model/dao.dart';
class Income {
int id, groupId, weekNumber, monthNumber, calendarYear;
String frequency, payoutDate, category, depositTo, description, status;
double expectedAmount, actualAmount;
Income(
this.id,
this.groupId,
this.expectedAmount,
this.actualAmount,
this.frequency,
this.payoutDate,
this.category,
this.depositTo,
this.status,
this.weekNumber,
this.monthNumber,
this.calendarYear,
[this.description]
);
}
here is my expense class object
import 'package:finsec/model/dao.dart';
class Expense{
int id, groupId
String frequency, paidDate, expCategory, description, status;
double expectedAmount, actualAmount;
Expense(
this.id,
this.groupId,
this.expectedAmount,
this.actualAmount,
this.frequency,
this.paidDate,
this.expCategory,
this.status,
[this.description]
);
}
// The base class for the different types of items the list can contain.
abstract class Dao<T> {
//queries
String get createTableQuery;
//abstract mapping methods
T fromMap(Map<String, dynamic> query);
List<T> fromList(List<Map<String,dynamic>> query);
Map<String, dynamic> toMap(T object);
}
import 'package:finsec/model/dao.dart';
import 'package:finsec/model/income/income.dart';
class IncomeDao implements Dao<Income> {
#override
Income fromMap(Map<String, dynamic> query) {
Income income = Income();
income.id = query["id"];
income.groupId = query["groupId"];
income.amount = query["amount"];
income.frequency = query["frequency"];
income.payoutDate = query["payoutDate"];
income.category = query["category"];
income.depositTo = query["depositTo"];
income.status = query["status"];
return income;
}
#override
Map<String, dynamic> toMap(Income object) {
return <String, dynamic>{
"id": object.id,
"groupId": object.groupId,
"amount": object.amount,
"frequency": object.frequency,
"payoutDate": object.payoutDate,
"category": object.category,
"depositTo": object.depositTo,
"status": object.status,
};
}
#override
List<Income> fromList(List<Map<String,dynamic>> query) {
List<Income> income = List<Income>();
for (Map map in query) {
income.add(fromMap(map));
}
return income;
}
}
i want to create function that takes any class object
Future<int> insertTransaction(T object) async {
var dao = new IncomeDao();
dao.toMap(object));
}
basically, i want to be able to call insertTransaction and pass any class object and then pass that object to the dao class. when i called dao.toMap(object)); in insertTransaction function. i get error message such as "The argument type 'T' can't be assigned to the parameter type 'Income'."
I guess flutter is not able to determine if object parameter is Income or expense etc. i tried using casting such as (Income)object but didnt work.
can someone help me on this? im trying to reuse my function (insertTransaction) instead of creating the same function for every object class such as income, expenses, events, etc...

just change T to dynamic
insertTransaction(dynamic object)

Related

Assign default value in flutter constructor

I have a class named vendor
class Vendor {
int id;
String name;
Vendor({this.id , this.name});
}
Now I have another class person, in this class I have a list of vendors I want to set default value in person constructor:
class Person {
List<Vendor> vendor;
Person({this.vendor});
}
I've tried this solution but it did not work
class Person {
List<Vendor> vendor;
Person({this.vendor}) : vendor = vendor ?? const [];
}
You can set default values for optional constructor parameters using =:
class Foo {
final List<String> strings;
Foo({this.strings = const ['example']});
}
class Bar {
final List<String> strings;
Bar([this.strings = const ['example']]);
}
print(Foo().strings); // prints '[example]'
print(Bar().strings); // prints '[example]'
Note, values passed in as optional parameters must be const.

Dart: Which is a better practice? Using 'late' or constructor initializer list

I am modelling a Dart class with the new null safety types in mind. I believe there are two effective ways to initialize non-nullable properties, calculated from a parameter.
For this example, we will use the Favourite class.
This class uses the initializer list in the constructor.
class Favourite {
int favouriteId;
Favourite({required this.favouriteId});
Favourite.mapFromJson(dynamic json)
: this.favouriteId = json["favouriteId"];
}
This class uses the 'late' keyword.
class Favourite {
late int favouriteId;
Favourite({required this.favouriteId});
Favourite.mapFromJson(dynamic json) {
this.favouriteId = json["favouriteId"];
}
}
When would you use one over the other? Using 'late' feels risky. If I added another named constructor, the compiler would not complain about 'favouriteId' not being initialized.
Are there other options?
Thank you!
Neither.
Use a default constructor that initializes the fields themselves and a factory constructor that handles deserializing the json object:
class Favourite {
final int favouriteId;
Favourite({required this.favouriteId});
factory Favourite.fromMap(Map<String, dynamic> map) {
final favouriteId = json['favouriteId'];
assert(favouriteId != null && favouriteId is int);
return Favourite(
favouriteId: favouriteId,
);
}
}
The late keyword can be a source of headache if you don't handle it properly, so in general don't use it unless you have to.
If you're sure the json will always have a "favouriteId", you can write it like this:
class Favourite {
int favouriteId;
Favourite({required this.favouriteId});
Favourite.mapFromJson(Map<String, dynamic?> json):
assert(() {
final favouriteId = json["favouriteId"];
return favouriteId != null && favouriteId is int;
}()),
favouriteId = json["favouriteId"] as int;
}
void main() {
dynamic m = {"favouriteId":2};
final favourite = Favourite.mapFromJson(m);
print("favourite id: ${favourite.favouriteId}");
}

Calling a private constructor - Constructor doesn't exist

I saw this answer and I am trying to replicate it in my code.
Below is the base class:
class ResponseObjectBase<T> {
bool success;
T responseObject;
ResponseObjectBase._fromJson(Map<String, dynamic> json){
success = true;
}
factory ResponseObjectBase.fromJson(Map<String, dynamic> json) {
if (T == OsGridRefModel) {
return OsGridRefModel.fromJson(json) as ResponseObjectBase<T>;
}
throw UnimplementedError();
}
}
And here is the derived class:
class OsGridRefModel extends ResponseObjectBase<OsGridRefModel>{
String descriptor;
double easting;
double northing;
OsGridRefModel.fromJson(Map<String, dynamic> json) : super._fromJson(json) {
this.descriptor = json['descriptor'] as String;
this.northing = json["northing"] as double;
this.easting = json["easting"] as double;
this.responseObject = this;
}
}
Inside of the derived class the super._fromJson(json) is throwing the following error:
The class 'ResponseObjectBase<OsGridRefModel>' doesn't have a constructor named '_fromJson'.
Try defining a constructor named '_fromJson' in 'ResponseObjectBase<OsGridRefModel>', or invoking a different constructor.
Thanks.

How to compare the type variable in "is" operator in Dart

I couldn't find a way to store the Type value in Map so that I could use it in is operator to check the validity of type using this map later on. Also, can is operator accept Type as a variable?
For eg, Below is hypothetical code solving the problem but it's invalid.
Map<String, Type> map = {
"sku": String,
"price": double,
"quantity": int,
};
dynamic value = 10;
if(value is map["quantity"]){
print("value is of type int and int is expected for quantity value");
}
You can do something like this:
class TypeCheck<T> {
const TypeCheck();
bool typeCheck(dynamic value) => value is T;
}
void main() {
Map<String, TypeCheck> map = {
"sku": TypeCheck<String>(),
"price": TypeCheck<double>(),
"quantity": TypeCheck<int>(),
};
dynamic value = 10;
if (map["quantity"]!.typeCheck(value)) {
print("value is of type int and int is expected for quantity value");
}
}
Im not sure I fully understand I understand what you are trying to do but why don't you try something like.
bool _validate(Map productDetails){
if (productDetails.containsKey("sold_individually") && productDetails["sold_individually"] is bool) {
//return true or false
}
else if (productDetails.containsKey("stock_quantity") && productDetails["stock_quantity"] is int){
//return true or false
}
else if (productDetails.containsKey("tax_class") && productDetails["tax_class"] is String && productDetails["tax_class"].isNotEmpty) {
//return true or false
} else {
//return true or false
}
}
As for the other part of your question you wont get an error but you will always return false. In contrast if you check if a variable is dynamic it will always return true.
I don't really understand your end goal. But from what you have, I don't think you are taking advantage of the strongly-typed nature of dart.
Assuming you are getting your map from an API, you could enforce
typing manually in your code as follows;
Map<String, Type> map = {
"sku": json['key'] as String,
"price": json['key'] as double,
"quantity": json['key'] as int,
};
And avoid using dynamic when declaring variables.
OR
In the case you have a user-defined type you what to compare, you can use the equatable package on a class for instance as follows;
class CustomMap extends Equatable {
String sky;
double price;
int quantity;
// here you put the fields of a class you want for two instances of a class to be equal.
#overide
List<Object> get props => [sky, price, quantity];
}
Update from your comment
You should have a custom class for the API objects for instance;
class Item extends Equatable {
String sku;
double price;
int quantity;
Item({this.sky, this.price, this.quantity});
// factory constructor
factory Item.fromMap(Map<String, dynmic> json) {
final sku = json['sku'] as String,
final price = (json['price'] as num) as double,
final quantity = json['quantity'] as num,
return Item(sku: sku, price: price, quantity: quantity);
}
// define equatable objects
#override
List<Object> get props => [sku, price, quantity];
}
Now you can use it as follows;
Future<Item> objectsFromService(Map<String, dynamic> json ) async {
http.Response response = http.get(url);
if(response.status == 200) {
final decodedJson = json.decode(response.body);
return Item.fromJson(decodedJson);
}else{
print('Error fetch data');
return null;
}
}
Hope it helps

How to insert a List<Class> into a Map<String, dynamic> in dart?

My problem is that I have a list of the following class:
class ingreso_Egreso_Dummy{
int tipo;
String monto;
String moneda;
String descripcion;
}
then I want to insert the data into a Map which later will be converted into a json and which I am creating like this:
Map<String, dynamic> body;
body = {
"Cod_Prom": "01",
"CodCli": "003526",
"Status": _index_status.toString(),
"NOMBRE": controller_nombre.text,
"APELLIDOS": controller_apellidos.text,
"solicitud":[{
"Cod_Solicit": 1.toString(),
"Fecha": DateFormat("y-d-M").format(DateTime.now()),
"Status_Solicit": "E",}],
"prestamo":[{
"Monto_Solicit":controller_monto_solic.text,
"Plazo":controller_plazo.text,
"Cod_TipoPlazo":_index_tipoplazo.toString(),
"Nombre_Resp":controller_nombreresp.text,
"Telf_Resp":controller_telefonoresp.text,}],
"Ingresos": [{
//// here I want create a loop that returns a map for each value
//// of the list like this:
//// "Descripcion": Listaingresos[i].descripcion;
})
}]
};
Every help is very appreciated, thank you.
// camelCaseStyle is a standard for class names for Dart
class IngresoEgresoDummy {
int tipo;
String monto;
String moneda;
String descripcion;
Map<String, dynamic> toJson(){
return {
'tipo': tipo,
'monto': monto,
'monedo': moneda,
'descripcion': descripcion
};
}
}
and after that
List<IngresoEgresoDummy> listaingresos= List();
Map<String, dynamic> body = {
// all your params
"Ingresos": listaingresos.map((ingreso) => ingreso.toJson()).toList()
// all your params
};