web-dev-qa-db-ja.com

Flutterクラスの継承

Flutterで最初のアプリを作成しています。このアプリは_sqlite database_を使用しています。モデルとリポジトリがあります。

コードレイアウト:

私には2つのモデルがあります(完成したアプリにはさらに多くあります)UserModelTimesheetModel、これらは両方ともBaseModelを拡張します

私は2つのリポジトリを持っています(完成したアプリではさらに多くなります)UserRepositoryTimesheetRepository、これらは両方ともBaseRepositoryを拡張します

私がやろうとしていること:BaseRepository内のgetAll()countAll()などの再利用可能なコードを使用して、すべてのリポジトリを拡張します。ベースリポジトリにはこの機能があり、テーブル名を設定して返されるModelを設定するだけで済みます。

エラー:BaseRepositoryBaseModelタイプを返しているため、コードからわかるように、タイムシートオブジェクトでall()関数を呼び出すと、次のエラーが発生します。 :タイプ 'List'はタイプ 'List'のサブタイプではありません

これを修正する方法がわかりません。何か提案がありますか?

BaseRepository

_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''');
  }
}
_

TimesheetRepository

_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);
  }


}
_

タイムシートで全員を呼び出すとき

_TimesheetRepository timesheet = TimesheetRepository();
timesheet.all();
_

基本モデル

_abstract class BaseModel {
  fromJson();
}
_

タイムシートモデル

_
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,
    );
  }
}

_
8
user3057745

同じオブジェクトの有効なインスタンスを作成できるようにするには、モデルの空のインスタンスを渡す必要があるので、私が行っている方法でのfromJsonの解析は行いません。ただし、アーキテクチャを機能させるには、いくつかの修正を行う必要があります。

1-ジェネリックを使用します。

BaseRepository

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''');
  }
}

2-スーパーコンストラクターを正しく呼び出す

TimesheetRepository

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());
}

3-fromJsonメソッドに正しいリターンを追加する

abstract class BaseModel {
  BaseModel fromJson({Map<String, dynamic> jsonData});
}

データベースと統合してテストできなかったので、動作するかどうかをお知らせください。

3
haroldolivieri

このようなallメソッドを作成した場合、 Dartがタイプを推測するには、このタイプの情報が必要だと思います。よくわからないけど

Future<List<T extends BaseModel>> all() async {
0
Rodrigo Bastos