无需强制转换即可访问子类对象的字段

Access field of subclassed object without casting

给出以下 类:

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];
}

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

 @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.
}

我错过了什么?

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

然而,从分析器的角度来看,state 也可能是一个 getter 函数,允许 不同的 [=24] 的 return =] 对象,每次 getter 被调用。因此,在 if 语句中第一次调用 getter 时,getter 可以 return 一个 SomeState 对象,但在 if 主体中, getter 可以 return 一个没有 someField getter.

的完全不同的对象

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

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