我有一个Flutter应用程序连接到Firestore数据库。我有一个对象层次结构,比如说抽象基类Vehicle
,子类Car
,Truck
等。这些类型的对象存储在数据库中。由于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
的具体子类中,并使用正确的类型:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
这种方法的问题是代码重复,因为实现在任何地方都是相同的。
还有其他选择吗?
1条答案
按热度按时间8xiog9wr1#
@mustBeOverridden
注解的支持,您可以将其添加到基类方法中。如果派生类忽略了重写它,分析器将发出警告。(然而,截至本文撰写之时,package:meta
的新版本尚未发布以添加该注解,但可能很快就会发布。)有关更多细节,请参见https://github.com/dart-lang/sdk/issues/30175。现在
Car().setInDB()
应该需要一个Car
参数,Truck().setInDB()
应该需要一个Truck
。