【问题标题】:Is there a generic Type in Dart like Class<T> in Java/Kotlin?Dart 中是否有像 Java/Kotlin 中的 Class<T> 这样的泛型类型?
【发布时间】:2022-07-21 21:21:52
【问题描述】:

在 Kotlin 中,我可以执行以下操作:

var myType : KClass<String>? = null

并且可以像这样分配给它:

myType = String::class

但不喜欢:

myType = Int::class // Type mismatch: inferred type in KClass<Int> but KClass<String>? was expected

在 Dart 中有类似的东西吗?我知道Type 类型,但它不是通用的,虽然它可以代表StringList&lt;int&gt;,但我似乎无法编写与我的Kotlin 示例类似的代码:

Type? t = null;

我可以分配给它:

t = String;

还有:

t = int;

但我希望第二个示例编译失败。我需要某种Type&lt;String&gt;。这在 Dart 中可行吗?

【问题讨论】:

  • 为什么不能'' is String1 is String?为什么需要通用的东西?或者如果你真的需要一个通用函数,为什么不bool test&lt;T&gt;(Object? object) =&gt; object is T;?或者,如果您需要编译时错误,那么 void test&lt;T&gt;(T object) {} 似乎也可以,但这似乎很愚蠢。只需首先声明您想要的类型。
  • @jamesdlin 我不需要测试类型,我认为方法的名称令人困惑,我将更改名称。一般来说,这是一个非常简单的示例,我可以展示我想要的东西,而不是真正的代码 - 我只想知道是否有类似 Type 的东西。
  • 我不知道Type&lt;T&gt; 应该做什么或意味着什么。对于您的aFunction 示例,您应该首先将其设为通用:aFunction&lt;T&gt;(T argument),您可以将其称为aFunction&lt;String&gt;('')(或省略类型并让它被推断)。如果您需要将Type 对象作为实际参数传递,那么不,您在编译时无能为力。但实际上你应该避免使用Type 对象;它们不是很有用。这听起来很可能是XY problem;这将有助于了解您真正想要做什么。
  • 我确实需要这种类型。也许我的例子不是最好的,让我再编辑一次。但我想无论如何都没有。
  • 我的代码已经可以工作了,只是我不喜欢 Kotlin 中没有的一些松散的类型安全性,我正在尝试了解我是否可以让它变得更好。

标签: dart generics


【解决方案1】:

Type 类不是通用的,不支持子类型检查(或任何其他合理的类型相关操作)。没有办法将它用于您正在尝试做的事情。

所以,不要。反正也没用。但是,在 Dart 中,您可以创建自己的 类型表示,这实际上是有用的,因为 Dart 不会删除类型参数,然后您可以让使用您的代码的人来代替它。

说:

class MyType<T> implements Comparable<MyType>{ // Or a better name.
  const MyType();
  Type get type => T;
  bool operator >=(MyType other) => other is MyType<T>;
  bool operator <=(MyType other) => other >= this;
  bool isInstance(Object? object) => object is T;
  R runWith<R>(R Function<T>() action) => action<T>();
  @override
  int get hashCode => T.hashCode;
  @override
  bool operator==(Object other) => other is MyType && T == other.type;
}

你可以这样写:

MyType<String?> type;
type = MyType<Null>(); // valid
type = MyType<String>(); // valid
type = MyType<Never>(); // valid
type = MyType<int>; // EEEK! compile-time error

您可以在需要将类型存储为值的地方使用它。

问题是,大多数时候您可以只使用类型变量,而创建一个实际值来表示类型是多余的。 因此,首先尝试只使用类型参数,而不是传递 TypeMyType 对象。只有当失败时,您才应考虑使用MyType。使用Type 可能是一个错误,因为除了进行== 检查之外,它对任何事情都没有好处,这与面向对象的子类型包含的想法是对立的。

【讨论】:

  • 我实际上有一个地图类型 -> 一些对象,我认为这是一个合理的用例?这也是 Flutter 做的事情,Element 保持一个 map Type -> InheritedElement。映射中作为值的对象与 T 是通用的,并且有一个“注册”函数 - 我想确保它是使用类型和在 T 中兼容的对象调用的。
  • 不能那样做,除了它是否是 == 另一个 Type 对象之外,您无法检查有关 Type 对象的任何内容。这就是为什么我总是建议使用其他东西(我也会向 Flutter 推荐这个。)哎呀,我会用 get&lt;T&gt;set&lt;T&gt; 方法创建一个 TypeMap 来让你对真实类型进行查找,而不是Type 对象在我考虑使用 Type 对象之前。
  • 是的,我明白你的意思。我会尝试看看其他解决方案,谢谢。
【解决方案2】:

我认为这是你能得到的最好的:

void main() {
  aFunction<String>(String, '');
  aFunction<String>(String, 1);
}

void aFunction<V>(Type type, V value) {
  print(value.toString());
}

如果你在 dartpad 中运行它,你会看到

aFunction<String>(type, 1);

不编译。

但这并不是很有效,因为类型不是 Dart 猜测的,您必须手动指定泛型类型。

我正在使用 Dart 2.17

【讨论】:

  • 是的,但在这种情况下,我不需要传递 Type 参数,因为它在正文中完全未使用。我希望能够只传递与类型参数 V 兼容的类型值。我编辑了问题以更简单的方式呈现我的想法(我希望如此)。
  • 这就是你在 Dart 中所能实现的。你不能应用你的 kotlin 逻辑来解决你的问题。你必须考虑 Dart。类型表示运行时类型,因此不能对其进行静态断言
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多