简体   繁体   English

如何强制参数与 static 具有与 object 相同的具体类型?

[英]How to enforce that a parameter is of the same static concrete type as the object?

I have a Flutter app connected to a Firestore database.我有一个连接到 Firestore 数据库的 Flutter 应用程序。 I have a hierarchy of objects, let's say for example with abstract base class Vehicle , with subclasses such as Car , Truck , etc. Objects of these types are stored in the database.我有一个对象层次结构,例如抽象基类 class Vehicle ,以及CarTruck等子类。这些类型的对象存储在数据库中。 Due to how Firestore works, it is better to make these classes immutable, ie to make them essentially represent a snapshot of the conceptual object instead of the mutable object itself.由于 Firestore 的工作方式,最好让这些类不可变,即让它们本质上代表概念 object 的快照,而不是可变的 object 本身。

When I want to update a Vehicle object in the database, I don't want users of Vehicle (ie other parts of my code) to have to specify the update as a dynamic map, eg vehicle.update({"speed": 42, "color": "red"}) , because this disables static checking of field names and types.当我想更新数据库中的Vehicle object 时,我不希望Vehicle的用户(即我代码的其他部分)必须将更新指定为动态 map,例如 vehicle.update vehicle.update({"speed": 42, "color": "red"}) ,因为这会禁用字段名称和类型的 static 检查。 Instead, I thought that the best way would be to make the users create the new snapshot they want, eg car.setInDB(updatedCar) .相反,我认为最好的方法是让用户创建他们想要的新快照,例如car.setInDB(updatedCar) Behind the scenes this just calls .set() on the corresponding document reference in Firestore.在幕后,这只是在 Firestore 中的相应文档引用上调用.set() Since the implementation would be the same on all subclasses of Vehicle , one could think of adding the method to Vehicle :由于实现在Vehicle的所有子类上都是相同的,因此可以考虑将方法添加到Vehicle

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

However, users of this method shouldn't be setting a vehicle of some concrete type with a vehicle of some other concrete type.但是,此方法的用户不应将某些具体类型的车辆与其他具体类型的车辆设置在一起。 Ie, a truck can only be updated with another truck snapshot, not a car snaphot.即,一辆卡车只能用另一辆卡车快照更新,而不是汽车快照。 This is already enforced at runtime through Firestore rules, but I'd rather have this checked statically.这已经通过 Firestore 规则在运行时强制执行,但我宁愿静态检查它。

These options occur to me:我想到了这些选项:

  1. Use the covariant keyword and make subclasses override the setInDB method with the corresponding type.使用covariant关键字并使子类覆盖具有相应类型的setInDB方法。

     abstract class Vehicle { Future<void> setInDB(covariant Vehicle updated) => database.set(this.dbLocation, updated) }
     class Car extends Vehicle { @override Future<void> setInDB(Car updated) => super.setInDB(updated) }

    The problem with this is I might forget to override the method if I add a new subclass.这样做的问题是,如果我添加一个新的子类,我可能会忘记重写该方法。 Also, users could do vehicle.setInDB(otherVehicle) , where vehicle has static type Vehicle , and the correctness of otherVehicle would be checked at runtime again.此外,用户可以执行vehicle.setInDB(otherVehicle) ,其中vehicle具有 static 类型Vehicle ,并且将在运行时再次检查otherVehicle的正确性。

  2. Only add the setInDB method to concrete subclasses of Vehicle , with the correct type:仅将setInDB方法添加到具有正确类型的Vehicle的具体子类:

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

    Etc. The problem with this approach is the code duplication, since the implementation is the same everywhere.等等 这种方法的问题是代码重复,因为实现在任何地方都是一样的。

Are there other options?还有其他选择吗?

  • Dart 2.19 adds analyzer support for a @mustBeOverridden annotation that you can add to a base class method. Dart 2.19 添加了对@mustBeOverridden注释的分析器支持,您可以将其添加到基本 class 方法中。 The analyzer then will emit a warning if a derived class neglects to override it.如果派生的 class 忽略覆盖它,那么分析器将发出警告。 (However, as of writing, a new version of package:meta has not been published yet to add that annotation, but presumably it will be published soon.) For more details, see https://github.com/dart-lang/sdk/issues/30175 . (然而,在撰写本文时, package:meta的新版本尚未发布以添加该注释,但据推测它很快就会发布。)有关更多详细信息,请参阅https://github.com/dart-lang/ SDK/问题/30175

  • Borrow the curiously recurring template pattern from C++ and apply it to Dart generics by making your derived classes extend (or mixin) a generic base class that is parameterized on the derived class. For example, I think that you could do:从 C++ 中借用奇怪的重复模板模式,并将其应用到 Dart generics,方法是使派生类扩展(或混入)在派生 class 上参数化的通用基类 class。例如,我认为您可以这样做:

     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> { }

    and now Car().setInDB() should require a Car argument, and Truck().setInDB() should expect a Truck .现在Car().setInDB()应该需要一个Car参数,而Truck().setInDB()应该需要一个Truck

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过镜像API获取静态方法的具体对象? - How to get concrete object of a static method via mirror API? 如何为给定类型的 Flutter 小部件强制执行某些参数值? - How can I enforce certain parameter values for Flutter widgets of a given type? 如何在泛型 Dart 方法中对泛型类型 T 实施实施约束? - How to enforce Implements constraint on generic type T in generic Dart method? 在扩展 function 中获取具体类型 - Getting concrete type in extension function 我该如何解决这个错误“参数类型'Object'不能分配给参数类型'int' - how can i solve this error"The argument type 'Object' can´t be assigned to the parameter type 'int' 如何使用Dart中的镜像获取泛型类型变量的具体类型? - How can I get the concrete type of a generic type variable using mirrors in Dart? 如何解决“参数类型‘对象’不能分配给参数类型‘字符串’ - How can i resolve "The argument type 'Object' can't be assigned to the parameter type 'String' 如何解决“参数类型‘对象?’ 不能分配给参数类型 'String'.dart(argument_type_not_assignable)”? - How can I resolve "The argument type 'Object?' can't be assigned to the parameter type 'String'.dart(argument_type_not_assignable)"? function 作为参数,在 dart 中具有泛型 object 返回类型 - function as parameter with generic object return type in dart 参数类型“对象?” 不能分配给参数类型“列表” - The argument type 'Object?' can't be assigned to the parameter type 'List'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM