为什么Iterable <declarationmirror>不能转换为Iterable <methodmirror>?

时间:2017-01-20 22:39:23

标签: dart

此代码在Dart VM(1.22.0-dev.9.0)上不起作用,但适用于DartPad(未知版本):

import 'dart:mirrors';

class Thing {
  Thing();
}

void g(ClassMirror c) {
  var constructors = c.declarations.values
      .where((d) => d is MethodMirror && d.isConstructor) as Iterable<MethodMirror>;
  print(constructors);
}

void main() {
  g(reflectClass(Thing));
}

结果:

Unhandled exception:
type 'WhereIterable<DeclarationMirror>' is not a subtype of type 'Iterable<MethodMirror>' in type cast where
  WhereIterable is from dart:_internal
  DeclarationMirror is from dart:mirrors
  Iterable is from dart:core
  MethodMirror is from dart:mirrors

#0      Object._as (dart:core-patch/object_patch.dart:76)
#1      g (file:///google/src/cloud/srawlins/strong/google3/b.dart:9:55)
#2      main (file:///google/src/cloud/srawlins/strong/google3/b.dart:14:3)
#3      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:261)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

(但在DartPad中会产生(MethodMirror on 'Thing')。)

请注意,如果我手工制作一些相互实现的类,并执行相同的操作,那么它可以工作:

abstract class DM {
  bool get t;
}

abstract class MM implements DM {
  MM();
  bool get t;
}

class _MM implements MM {
  bool get t => true;
}

void f(Map<dynamic, DM> dms) {
  var mms = dms.values.where((dm) => dm is MM && dm.t) as Iterable<MM>;
  print(mms);
}

void main() {
  f({1: new _MM()});
}

很好地打印:(Instance of '_MM')

1 个答案:

答案 0 :(得分:0)

仅仅因为.where()返回的可迭代只能包含MethodMirror个实例,所以不允许强制转换。该类型从c.declarations.values传播,即DeclarationMirror。 虽然您可以将DeclarationMirror投射到MethodMirror,但是从Iterable<DeclarationMirror>Iterable<MethodMirror>的投射无效,因为这些与迭代之间没有任何关系。

似乎当dart2js为JS构建时,会删除一些泛型类型,这就是DartPad中的原因。

您可以创建新的List<MethodMirror>

import 'dart:mirrors';

class Thing {
  Thing();
}

void g(ClassMirror c) {
  var constructors = new List<MethodMirror>.from(
      c.declarations.values.where((d) => d is MethodMirror && d.isConstructor));
  print(constructors);
}

void main() {
  g(reflectClass(Thing));
}

有一个悬而未决的问题可以让这更容易https://github.com/dart-lang/sdk/issues/27489