dart 如何强制参数与对象具有相同的静态具体类型?

uubf1zoe  于 2023-02-01  发布在  其他
关注(0)|答案(1)|浏览(121)

我有一个Flutter应用程序连接到Firestore数据库。我有一个对象层次结构,比如说抽象基类Vehicle,子类CarTruck等。这些类型的对象存储在数据库中。由于Firestore的工作原理,最好使这些类不可变。即使它们本质上表示概念对象的"快照"而不是可变对象本身。
当我想要更新数据库中的Vehicle对象时,我不希望Vehicle的用户(我的代码的其他部分)必须将更新指定为动态Map,例如vehicle.update({"speed": 42, "color": "red"}),因为这禁用了对字段名和类型的静态检查。相反,我认为最好的方法是让用户创建他们想要的新快照,例如car.setInDB(updatedCar)。在幕后,它只是在Firestore中相应的文档引用上调用.set()。由于在Vehicle的所有子类上实现都是相同的,因此可以考虑将该方法添加到Vehicle中:

abstract class Vehicle {
  Future<void> setInDB(Vehicle updated) 
      => database.set(this.dbLocation, updated)
}

但是,使用此方法的用户不应该将某个具体类型的车辆设置为其他具体类型的车辆。也就是说,卡车只能使用另一个卡车快照更新,而不是汽车快照。这已经通过Firestore规则在运行时强制执行,但我更希望静态检查这一点。
我想到了这些选项:
1.使用covariant关键字并使子类用相应的类型重写setInDB方法。
x一个一个一个一个x一个一个二个x
这样做的问题是,如果添加一个新的子类,我可能会忘记覆盖该方法,而且,用户可以执行vehicle.setInDB(otherVehicle),其中vehicle具有静态类型Vehicle,并且otherVehicle的正确性将在运行时再次检查。
1.仅将setInDB方法添加到Vehicle的具体子类中,并使用正确的类型:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
这种方法的问题是代码重复,因为实现在任何地方都是相同的。
还有其他选择吗?

8xiog9wr

8xiog9wr1#

  • Dart 2.19增加了分析器对@mustBeOverridden注解的支持,您可以将其添加到基类方法中。如果派生类忽略了重写它,分析器将发出警告。(然而,截至本文撰写之时,package:meta的新版本尚未发布以添加该注解,但可能很快就会发布。)有关更多细节,请参见https://github.com/dart-lang/sdk/issues/30175
  • 从C++中借用curiously recurring template pattern并将其应用于Dart泛型,方法是让派生类扩展(或mixin)一个泛型基类,该基类在派生类上参数化。
abstract class Vehicle<DerivedVehicle extends Vehicle<DerivedVehicle>> {
  Future<void> setInDB(DerivedVehicle updated)
      => database.set(this.dbLocation, updated)
}

class Car extends Vehicle<Car> {
}

class Truck extends Vehicle<Truck> {
}

现在Car().setInDB()应该需要一个Car参数,Truck().setInDB()应该需要一个Truck

相关问题