首页 > 解决方案 > 不强制转换的子类对象的访问字段

问题描述

给定以下类:

abstract class ParentState extends Equatable {
  const SomeState();
}

class SomeState extends ParentState {
  const SomeState({required this.someField});

  final String someField;

  @override
  List<Object> get props => [someField];
}

someField如果当前状态是我的方法中的类型SomeState,我想访问mapEventToState,但编译器不允许这样做:

 @override
  Stream<ParentState> mapEventToState(
    ParentEvent event,
  ) async* {
    if (state is SomeState) {
        print(state.someField); // Error: The getter 'someField' isn't defined for the type 'ParentState'.
    }
}

但是,如果我手动创建一个ParentState变量,它会按预期工作:

ParentState state = SomeState(someField: 'test');

if (state is SomeState) {
   print(state.someField); // Works.
}

此外,手动铸造mapEventToState作品,但这不应该是必需的:

if (state is SomeState) {
    print((state as SomeState).someField); // Works.
}

我错过了什么?

标签: flutterdartinheritancepolymorphism

解决方案


在您的第一个错误示例中,它似乎state是周围类中的一个字段,具有自动生成的 getter 和 setter。

然而,从分析器的角度来看,它state也可能是一个 getter 函数,它允许在每次调用 getter 时返回不同的对象。因此,在if语句中第一次调用 getter 时,getter 可以返回一个SomeState对象,但在ifbody 中,getter 可以返回一个完全不同的对象而没有someFieldgetter。

要解决这个问题,您只需要在函数中创建变量的本地副本并使用该副本而不是类字段:

@override
Stream<ParentState> mapEventToState(
  ParentEvent event,
) async* {
  final stateCopy = state;
  if (stateCopy is SomeState) {
      print(stateCopy.someField);
  }
}

推荐阅读