是否可以在Dart类上要求泛型类型参数?

mat*_*rey 4 dart flutter

尤其是Dart 2以来的一个常见问题是,是否有可能在某些或所有类型上都需要某些或所有通用类型参数-例如,List<int>代替ListMyType<Foo>代替MyType

并非总是很清楚目的是什么-即这是一个风格问题(您/您的团队喜欢看到类型),防止错误(忽略类型参数似乎会给您/您的团队带来更多错误)还是一个契约问题(您的库需要一个类型参数)。

例如,在上dart-misc,用户写道:

基本上,如果我有这个:

abstract class Mixin<T> {}
Run Code Online (Sandbox Code Playgroud)

我不具备指定类型:

// Works class Cls extends Object with Mixin<int> {} // ...also works
class Cls extends Object with Mixin {}
Run Code Online (Sandbox Code Playgroud)

有什么办法可以使第二个不允许?

mat*_*rey 6

严格地说,是的,没有。

如果要强制在您自己的项目中始终使用类型参数(而不是依赖类型推断或默认值),则可以使用可选的 linter规则,例如always_specify_types。请注意,该规则AVOID redundant type arguments on generic invocations在许多情况下违反了Dart官方指南的建议。

如果要强制执行的通用类型的参数是始终使用默认将被混淆-如List隐含的意思List<dynamic>,没有这样的皮棉存在尚未 -虽然我们计划将以此为模式的分析仪:https://github.com / dart-lang / sdk / issues / 33119


无论上述建议会帮助自己,但是如果你正在创建一个图书馆的来使用,你可能会问,如果你能需要一个类型参数来使用你的类。例如,从上面:

abstract class Mixin<T> {}
abstract class Class extends Object with Mixin {}
Run Code Online (Sandbox Code Playgroud)

您可以做的第一件事是将默认范围添加到T

// If T is omitted/not inferred, it defaults to num, not dynamic.
abstract class Mixin<T extends num> {}
Run Code Online (Sandbox Code Playgroud)

如果您想允许任何事情,但是想在T动态时难以使用类/混合,则可以选择其他默认界限,例如Object,甚至更好,我建议void

在实践中,我void通常是指“任何东西,我都不关心元素”

abstract class Mixin<T extends void> {
  T value;
}

class Class extends Mixin {}

void main() {
  var c = Class();
  // Compile-time error: 'oops' isn't defined for the class 'void'.
  c.value.oops();
}
Run Code Online (Sandbox Code Playgroud)

(您也可以Object用于此目的)

如果这是一个受您控制的类,则可以添加一个断言,以防止以您不支持或期望的方式使用该类。例如:

class AlwaysSpecifyType<T> {
  AlwaysSpecifyType() {
    assert(T != dynamic);
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,您可以编写一个自定义的lint或工具来禁止遗漏某些泛型类型参数,但这可能是最繁重的工作,并且如果有任何以前的方法对您有用,我强烈建议您这样做!