在Dart2中,用于泛型的正确“任何”类型是什么?

时间:2018-03-15 20:12:12

标签: dart

AngularDart有一个名为In [686]: np.append(p1[:, None], np.repeat((p2 - p1) / 10, [10, 10, 10]).reshape ...: (3, -1).cumsum(axis=1), axis=1) Out[686]: array([[ 0. , 1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. , 10. ], [ 1. , 0.8, 1.6, 2.4, 3.2, 4. , 4.8, 5.6, 6.4, 7.2, 8. ], [ 2. , 0.6, 1.2, 1.8, 2.4, 3. , 3.6, 4.2, 4.8, 5.4, 6. ]]) In [687]: _.shape Out[687]: (3, 11) 的类,即AppView

为每个使用abstract class AppView<T> {}注释的类生成其中一个(至少):

@Component

我在框架的其他地方有代码,不关心这个// file.dart @Component(...) class DashboardComponent {} // file.template.dart (Generated) class ViewDashboardComponent extends AppView<DashboardComponent> {} 类型是什么。我对Dart 2有点困惑,使用“正确”,“任何”类型。例如,我可以使用:

  • T
  • AppView
  • AppView<dynamic>
  • AppView<Object>
  • AppView<Null>

我认为其中不止一个会“奏效”。但在这种情况下哪个是“正确的”?

2 个答案:

答案 0 :(得分:4)

您可以在任何地方使用AppView(或AppView<dynamic>)。我可以想到两个例子,这会让你遇到麻烦:

  1. 如果您实例化 AppView,您肯定需要该类型参数。如果不这样做,请参阅以下错误:

    $ cat a.dart
    void main() {                                                                                                                          
      List<dynamic> a = ["one", "two", "three"];
      List<String> b = a;
    }
    $ dart --preview-dart-2 a.dart
    Unhandled exception:
    type 'List' is not a subtype of type 'List<String>' where
      List is from dart:core
      List is from dart:core
      String is from dart:core
    
    #0      main (file:///Users/sam/a.dart:3:20)
    #1      _startIsolate.<anonymous closure> (dart:isolate/isolate_patch.dart:279:19)
    #2      _RawReceivePortImpl._handleMessage (dart:isolate/isolate_patch.dart:165:12)
    
  2. 如果你为一个需要一个或多个涉及T的类型参数的闭包的网站分配一个闭包,你会看到一个“使用动态为底部”的静态错误(来自分析器),也可能是运行时错误:

    $ cat f.dart                                                       
    
    void main() {
      List a = <String>["one", "two", "three"];
      a.map((String s) => s.toUpperCase());
    
      List b = ["one", "two", "three"];
      b.map((String s) => s.toUpperCase());
    }
    $ dart --preview-dart-2 f.dart
    f.dart:3:9: Error: A value of type '(dart.core::String) → dart.core::String' can't be assigned to a variable of type '(dynamic) → dynamic'.
    Try changing the type of the left hand side, or casting the right hand side to '(dynamic) → dynamic'.
      a.map((String s) => s.toUpperCase());
            ^
    f.dart:6:9: Error: A value of type '(dart.core::String) → dart.core::String' can't be assigned to a variable of type '(dynamic) → dynamic'.
    Try changing the type of the left hand side, or casting the right hand side to '(dynamic) → dynamic'.
      b.map((String s) => s.toUpperCase());
            ^
    
  3. (我不确定任何 Dart工具还有完整的Dart 2运行时和编译时语义,所以这可能会略有改变。)

    在这些情况下,最好使用generic classesgeneric methodsgeneric typedefs来封装对于给定范围,对象类型参数的值可能是什么。< / p>

    我怀疑Dart 2中dynamicObject之间存在差异,我认为Günter在他的回复中涵盖了这一点,但如果你的代码“不关心这个T类型是什么” ,那么你可能没有在组件上调用任何方法。

    编辑:无效

    在这种情况下,

    AppView<void>可能是一个不错的选择,因为实际检查实际上从不接触底层组件(Object可能用于相同的目的)。了解我们如何被允许访问List<void>的属性,但不能访问元素的属性:

    $ cat g.dart
    void main() {
      var c = <String>["one", "two", "three"];
      fn(c);
      fn2(c);
    }
    
    int fn(List<void> list) => list.length;
    
    int fn2(List<void> list) => list.first.length;
    $ dart --preview-dart-2 g.dart
    g.dart:9:40: Error: The getter 'length' isn't defined for the class 'void'.
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
    int fn2(List<void> list) => list.first.length;
                                           ^
    

答案 1 :(得分:1)

我认为你比我更清楚,但我的尝试

  • AppView - 作品 - 与AppView<dynamic>
  • 相同
  • AppView<dynamic> - 作品 - 真的意味着任何类型
  • AppView<Object> - 作品 - 真的意味着任何类型
  • AppView<Null> - 不起作用,只有nullvoid值匹配T
  • AppView<void> - 无效,只有nullvoid值匹配T
    AppView<void> - 有效(请参阅以下来自lrn的评论)

<dynamic><Object>之间的区别在于T类型的值与T == dynamic属性或方法访问权限不同静态检查,而对于T == Object,只有Object类的方法和属性可以在没有先前强制转换的情况下访问。