当接口未定义该字段时,如何访问使用接口传递的对象上的字段

How to access a field on an object that has been passed using an interface, when the interface does not define that field

提问人:technolion 提问时间:6/12/2023 最后编辑:technolion 更新时间:6/12/2023 访问量:31

问:

我正在使用外部 API,我无法修改它,并且想要访问未由其接口定义的对象上的字段。

接口未定义字段。 和 implement 并且都有一个附加的字段 类型 。IFooheadersFooBarIFooheadersString

这在 Dart 中是可行的,但远非优雅:

void doSomething (IFoo data) {
    String headers;
    if (data is Foo) {
      headers = data.headers;
    } else if (data is Bar) {
      headers = data.headers;
    }
}

这在 dart 中不起作用

void doSomething (IFoo data) {
    String headers;
    if (data is Foo || data is Bar) {
      headers = data.headers;
    }
}

有没有比上面第一个例子更优雅的方式?

DART 类型 接口 转换

评论

1赞 Ahmad F 6/12/2023
似乎是某些类型(基本上)之间的一种共享属性,为什么不定义它呢?如果它不必在 ,至少在这种情况下可以做一些接口隔离......headersIFooIFooIFoo
0赞 technolion 6/12/2023
我不是 API 的作者,无法更改接口。我相应地更新了问题。感谢您的输入。

答:

1赞 Ahmad F 6/12/2023 #1

有没有比上面第一个例子更优雅的方式?

从更深层次来看,在这种情况下,我建议的“优雅方式”是遵循接口隔离原则

很明显,属性的声明对于某些类型(例如 和 )是通用的,但是,如果声明它没有意义(出于代码设计原因,例如还有其他类型的不需要声明),则为具有该属性的所有子类型使用通用类型仍然是明智的。headersFooBarIFooIFooheadersheaders

在 Dart 中,使用 mixin 是实现它的正确方法。例:

abstract class IFoo {}

mixin MixinFoo {
  String get headers => 'MixinFoo';
}

class Foo with MixinFoo implements IFoo {
  @override
  String get headers => 'Foo';
}

class Bar with MixinFoo implements IFoo {
  @override
  String get headers => 'Bar';
}

请注意,和仍然是类型,此外,它们也是!这意味着它们具有属性,而不会混淆 s 的逻辑。FooBarIFooMixinFooheadersIFoo

因此,您可以将给定值强制转换为:

void doSomething (IFoo data) {
    String headers;
    MixinFoo? dataMixin = (data is MixinFoo ? data : null) as MixinFoo?;

    // if the data is not a MixinFoo, then dataMixin will be null
    if (dataMixin != null) {
      headers = dataMixin.headers;
    }
}

或者(因为我们谈论的是“优雅的方式”🙂):

void doSomething (IFoo data) {   
    try {
        String headers;
        final dataMixin = data as MixinFoo;
        headers = dataMixin.headers;
    }
    on TypeError catch(_) {
          // fallback, if the data is not a MixinFoo...
    }
}

现在任何类型都可以铸造,从代码设计的角度来看,这更有意义。MixinFoo

评论

0赞 technolion 6/12/2023
太棒了,谢谢!