Flutter类继承

use*_*745 7 inheritance class dart flutter

我正在Flutter中构建我的第一个应用,该应用正在使用sqlite database。因此,我有模型和存储库。

代码布局:

我有2款(将有更多的在成品应用程序)UserModelTimesheetModel这些都延长BaseModel

我有2个存储库(将有更多的在成品应用程序) UserRepositoryTimesheetRepository这些都延伸BaseRepository

我所试图做的事:我想有可重用的代码,如:getAll()countAll()在等BaseRepository这样所有的扩展基本信息库具有此功能的资料库和所有我需要做的是设置表名称并设置返回Model

错误:您可以从我的代码中看到,因为的BaseRepository返回BaseModel类型,当我all()在时间表对象上调用函数时,出现以下错误:类型'列表'不是类型'列表'的子类型

我不确定如何解决此问题,请提出任何建议?

基本资料库

abstract class BaseRepository {
  final String table;
  final model;

  BaseRepository({this.table, this.model});

  // Retrieve all the items
  Future<List<BaseModel>> all() async {
    final sql = '''SELECT * FROM $table''';
    final data = await db.rawQuery(sql);

    List<BaseModel> forms = List();
    for (final node in data) {
      final form = model.fromJson(jsonData: node);
      forms.add(form);
    }
    return forms;
  }

  // Find an item by its ID
  Future findById(int id) async {
    final sql = '''SELECT * FROM $table
    WHERE id = ?''';

    List<dynamic> params = [id];
    final data = await db.rawQuery(sql, params);

    final form = model.fromJson(jsonData: data.first);
    return form;
  }

  // Count all the items
  Future<int> count() async {
    final data = await db.rawQuery('''SELECT COUNT(*) FROM $table''');

    int count = data[0].values.elementAt(0);
    int idForNewItem = count++;
    return idForNewItem;
  }

  // clear the table
  Future<void> delete() async {
    // truncate current database table
    await db.rawQuery('''DELETE FROM $table''');
  }
}
Run Code Online (Sandbox Code Playgroud)

时间表资料库

class TimesheetRepository extends BaseRepository {
  String table = 'timesheets';
  TimesheetModel model = new TimesheetModel();

  // Search for a item by its name
  Future<List<TimesheetModel>> findByDate(DateTime dateTime) async {
    final String date = DateFormat("yyyy-MM-dd").format(dateTime);
    final sql = '''SELECT * FROM $table WHERE timesheet_date = ?''';
    List<dynamic> params = [date];

    final data = await db.rawQuery(sql, params);
    List<TimesheetModel> forms = List();

    for (final node in data) {
      final form = TimesheetModel.fromJson(jsonData: node);
      forms.add(form);
    }
    return forms;
  }

  // Add a new item
  Future<void> store(TimesheetModel timesheet) async {
    final sql = '''INSERT INTO $table
    (
      user_id,
      timesheet_date,
      start_time,
      end_time,
      json,
      is_uploaded
    )
    VALUES (?,?,?,?,?,?)''';

    List<dynamic> params = [
      timesheet.userId,
      DateFormat("yyyy-MM-dd").format(timesheet.timesheetDate),
      timesheet.startTime,
      timesheet.endTime,
      convert.json.encode(timesheet.json),
      timesheet.is_uploaded,
    ];

    final result = await db.rawInsert(sql, params);
    DatabaseCreator.databaseLog('Add form', sql, null, result, params);
  }


}
Run Code Online (Sandbox Code Playgroud)

在时间表上拨打电话时

TimesheetRepository timesheet = TimesheetRepository();
timesheet.all();
Run Code Online (Sandbox Code Playgroud)

基本型号

abstract class BaseModel {
  fromJson();
}
Run Code Online (Sandbox Code Playgroud)

时间表模型


class TimesheetModel extends BaseModel {
  int id;
  int userId;
  DateTime timesheetDate;
  String startTime;
  String endTime;
  Map json = {
    "task": "",
    "detail": "",
    "notes": "",
  };
  bool is_uploaded;

  TimesheetModel({
    this.id,
    this.userId,
    this.timesheetDate,
    this.startTime,
    this.endTime,
    this.json,
    this.is_uploaded,
  });


  fromJson({Map<String, dynamic> jsonData}) {

    return TimesheetModel(
      id: jsonData['id'] as int,
      userId: jsonData['user_id'] as int,
      timesheetDate: timesheetDate,
      startTime: jsonData['start_time'],
      endTime: jsonData['end_time'],
      is_uploaded: hasUploaded,
    );
  }
}

Run Code Online (Sandbox Code Playgroud)

har*_*eri 5

我不会按照您的方式进行解析 fromJson ,因为您需要传递模型的空实例才能创建同一对象的有效实例。但为了让您的架构正常工作,您需要进行一些更正:

1 - 使用泛型。

基础存储库

abstract class BaseRepository<T extends BaseModel> {
  BaseRepository({this.table, this.model});

  final String table;
  final T model;

  // Retrieve all the items
  Future<List<T>> all() async {
    final sql = '''SELECT * FROM $table''';
    final data = await db.rawQuery(sql);

    return data.map((node) {
      return model.fromJson(jsonData: node);
    }).toList();
  }

  Future<T> findById(int id) async {
    final sql = '''SELECT * FROM $table
    WHERE id = ?''';

    final data = await db.rawQuery(sql, [id]);

    return model.fromJson(jsonData: data.first);
  }

  // Count all the items
  Future<int> count() async {
    final data = await db.rawQuery('''SELECT COUNT(*) FROM $table''');

    int count = data[0].values.elementAt(0);
    int idForNewItem = count++;
    return idForNewItem;
  }

  // clear the table
  Future<void> delete() async {
    // truncate current database table
    await db.rawQuery('''DELETE FROM $table''');
  }
}
Run Code Online (Sandbox Code Playgroud)

2 - 正确调用超级构造函数

时间表存储库

class TimesheetRepository extends BaseRepository<TimesheetModel> {
  ///IMHO you should not pass TimesheetModel instance here, it is really redundant
  ///you can create a parse class that receives the type and a json and does the 
  ///trick
  TimesheetRepository() : super(table: 'timesheets', model: TimesheetModel());
}
Run Code Online (Sandbox Code Playgroud)

3 - 将正确的返回添加到您的fromJson方法中

abstract class BaseModel {
  BaseModel fromJson({Map<String, dynamic> jsonData});
}
Run Code Online (Sandbox Code Playgroud)

我无法测试它与数据库的集成,所以请告诉我这是否有效。