gpt4 book ai didi

sqlite - Dart-使用泛型将List 转换为List

转载 作者:行者123 更新时间:2023-12-03 02:55:35 27 4
gpt4 key购买 nike

我是Flutter和Dart的新手,来自本地Android。

Android有一个非常好的数据库抽象架构,称为Room Persistence Library。据我所知,使用MVVM / MVC设计模式的Flutter没有这样的数据库抽象体系结构。

我的解决方案是自己创建Dart版本。经过几次头痛之后,我几乎完成了所有工作,但似乎无法使LiveData使用泛型正常工作。

我像这样设置类(class):

class LiveData<T> {
...
}

现在,当我想返回一些数据时,它可以是 ObjectList<Object>。我发现了一个巧妙的技巧,可以区分 T和两者:
...

// Parse response
// This checks if the type is an instance of a single entity or a list.
if (entity is T) {
cachedData = rawData.isEmpty ? null : entity.fromMap(rawData.first) as T;
} else {
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
}

...

问题出在第二块:
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;

与错误:
 - Unhandled Exception: type 'List<Entity>' is not a subtype of type 'List<Vehicle>' in type cast

问题就变成了:当我无权访问 Entity类时,如何将 Vehicle转换为 Vehicle。仅将其实例分配给 Entity entity变量。

这是一个片段,以演示我对 Vehicle的访问:
final Entity entity;

...assign Vehicle instance to entity...

print(entity is Vehicle) // True

我尝试使用 .runtimeType无济于事。我还考虑过将 LiveData分为两个类,第二个是 LiveDataList。尽管这似乎是不对代码进行错误检查的最简单解决方案,但它可能会打扰我(故意是双关语)并破坏原本非常漂亮的Room端口。



作为一个临时解决方案,我将构建逻辑抽象为一个通用函数,该函数将传递给构造函数中的 LiveData
final T Function(List<Map<String, dynamic>> rawData) builder;

现在,我将其命名为 cachedData,而不是之前的代码。
// Parse response
cachedData = builder(rawData);

访问 LiveData<List<Vehicle>>中的所有车辆时,调用 Dao<Vehicle>的构造函数是:
class VehicleDao implements Dao<Vehicle> {
...

static LiveData<List<Vehicle>> get() {
return LiveData<List<Vehicle>>(
...
(rawData) => rawData.map((e) => Vehicle.fromMap(e)).toList(),
...
);
}
}

最佳答案

在Dart中(实际上在许多语言中),泛型都带有继承的概念。您会认为,如果Bar继承自Foo,那么该List<Bar>也将可转换为List<Foo>

实际上,由于泛型的工作原理,情况并非如此。当您有通用类时,每次您使用具有不同类型的该类时,该类型都被视为完全独立的类。这是因为当编译器编译这些类型时,class MyGenericType<Foo> extends BaseClassclass MyGenericType<Bar> extends BaseClass基本上会转换为class MyGenericType_Foo extends BaseClassclass MyGenericType_Bar extends BaseClass之类的东西。

看到问题了吗? MyGenericType_FooMyGenericType_Bar不是彼此的后代。他们是彼此的 sibling ,都从BaseClass扩展。这就是为什么当您尝试将List<Entity>转换为List<Vehicle>时,强制转换不起作用的原因,因为它们是同级类型,而不是父类(super class)型和子类型。

综上所述,虽然不能基于通用类型参数的关系将一种通用类型直接转换为另一种通用类型,但是对于List,有一种方法可以将一种List类型转换为另一种类型:cast方法。

List<Entity> entityList = <Entity>[...];
List<Vehicle> vehicleList = entityList.cast<Vehicle>(); // This cast will work

但是要注意的一件事是,如果您是从父类(super class)型泛型转换为子类型泛型,并且列表中的所有元素都不都是该新类型,则此转换将引发错误。

关于sqlite - Dart-使用泛型将List <SuperType>转换为List <SubType>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60461815/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com