class ActivityItem {}
class Activity<T extends ActivityItem> {
T item;
Activity(this.item);
}
class Type1ActivityItem extends ActivityItem {
final String data;
Type1ActivityItem(this.data):super();
}
passType1(Activity<Type1ActivityItem> item) {
print(item);
}
main() {
Activity activity = Activity(Type1ActivityItem('data1'));
print(passType1(activity as Activity<Type1ActivityItem>)); // ERROR
}
在运行时掷飞镖
未捕获的错误:TypeError:“ Activity
当通用类型信息丢失时,有点困惑以了解
方案1:
print(Activity(Type1ActivityItem('data1')) is Activity<Type1ActivityItem>); // True
Dart能够根据构造函数参数推断出通用类型
方案2:
Activity activity1 = Activity(Type1ActivityItem('data1'));
print(activity1 is Activity<Type1ActivityItem>); // False
看起来像在分配给活动1时,通用类型信息丢失了。
方案3:
Activity activity2 = Activity<Type1ActivityItem>(Type1ActivityItem('data1'));
print(activity2 is Activity<Type1ActivityItem>); // True
即使在分配给activity2之后,泛型类型仍然存在...
答案 0 :(得分:1)
活动活动= ...
这是错误发生的原因。这为activity
提供了类型Activity<ActivityItem>
,这是一种不能向下转换为Activity<Type1ActivityItem>
的独特类型。
可以通过以下几种方法解决此问题:
Activity activity = Activity<Type1ActivityItem>(Type1ActivityItem('data1'));
Activity<Type1ActivityItem> activity = Activity(Type1ActivityItem('data1'));
var activity = Activity(Type1ActivityItem('data1'));
final activity = Activity(Type1ActivityItem('data1'));
class BaseActivityItem {
final int base = 1;
}
class SubActivityItem extends BaseActivityItem {
final int sub = 2;
}
class Activity<T extends BaseActivityItem> {
T item;
Activity(this.item);
}
passType1(Activity<SubActivityItem> item) {
print('passType1 received: $item');
}
main() {
// The specified variable type will always be the static type of the variable.
// Here `Activity` is shorthand for `Activity<BaseActivityItem>`.
// Activity(SubActivityItem()) is a valid value for `Activity<BaseActivityItem>`.
Activity activity = Activity(SubActivityItem());
assert(activity is Activity<BaseActivityItem>);
// `activity.item` runtime type is, as expected, `SubActivityItem`. But, its
// interface is limited to `BaseActivityItem`.
assert(activity.item is SubActivityItem);
print(activity.item.base); // 1
// The following will not compile because item has type `BaseActivityItem`.
//print(activit.item.sub);
// It can be downcast to `SubActivityItem`.
print((activity.item as SubActivityItem).sub); // 2
// `activity`'s runtime type is actually
// Activity<BaseActivityItem> so casting will fail.
print(activity is Activity<SubActivityItem>); // false
print('------------------------------------------------');
// Here we have another activity with the runtime type of
// Activity<SubActivityItem>. The actual Activity instance
// is a Activity<SubActivityItem>, but its interface is
// limited by `Activity` i.e. `Activity<BaseActivityItem>`.
Activity subRuntimeType = Activity<SubActivityItem>(SubActivityItem());
assert(subRuntimeType is Activity<BaseActivityItem>);
assert(subRuntimeType is Activity<SubActivityItem>);
print(subRuntimeType.item.base); // 1
// This will fail to compile because item's interface is
// BaseActivityItem.
//print(subRuntimeType.item.sub);
// However it can be downcast:
print((subRuntimeType.item as SubActivityItem).sub); // 2
print((subRuntimeType as Activity<SubActivityItem>).item.sub); // 2
// This can be properly passed to `passType1` because dart knows
// that `subRuntimeType` is an Activity<SubActivityItem>.
passType1(subRuntimeType);
print('------------------------------------------------');
// The constructor will return the correct type.
Activity<SubActivityItem> subType = Activity(SubActivityItem());
// The following will fail to compile as the constructor return value
// is not valid for variable type:
//... subType = Activity(BaseActivityItem());
//... subType = Activity<BaseActivityItem>(SubActivityItem());
assert(subType is Activity);
assert(subType is Activity<SubActivityItem>);
print(subType.item.base); // 1
print(subType.item.sub); // 2
passType1(subType);
print('------------------------------------------------');
// These will infer the type from rhs:
var inferVarType = Activity(SubActivityItem());
final inferFinalType = Activity(SubActivityItem());
print(inferVarType.item.sub); // 2
print(inferFinalType.item.sub); // 2
passType1(inferVarType);
passType1(inferFinalType);
}