英文:
How to access a field on an object that has been passed using an interface, when the interface does not define that field
问题
我正在使用一个无法修改的外部API,并希望访问一个对象上未由其接口定义的字段。
接口 IFoo
未定义字段 headers
。
Foo
和 Bar
都实现了 IFoo
,并都有一个额外的类型为 String
的字段 headers
。
这在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;
}
}
有没有比上面第一个示例更优雅的方法?
英文:
I am using an external API, which I cannot modify and want to access a field on an object that is not defined by its interface.
Interface IFoo
does not define the field headers
.
Both Foo
and Bar
implement IFoo
and both have an additional field headers
of type String
.
This is working in Dart, but is far from elegant:
void doSomething (IFoo data) {
String headers;
if (data is Foo) {
headers = data.headers;
} else if (data is Bar) {
headers = data.headers;
}
}
This does not work in dart:
void doSomething (IFoo data) {
String headers;
if (data is Foo || data is Bar) {
headers = data.headers;
}
}
Is there a more elegant way than the above first example?
答案1
得分: 1
Is there a more elegant way than the above first example?
在上面的第一个示例之外,是否有更加优雅的方法?
Taking a look at a higher level of the whole picture, the "elegant way" that I'd suggest in this case is following the Interface Segregation Principle.
从整体上看,我建议在这种情况下采用更加优雅的方法是遵循接口隔离原则。
It's clear that the declaration of the headers
property is common for some of the types (such as Foo
and Bar
), however, if declaring it in IFoo
does not make sense (for code design reasons, such as there are other types of IFoo
don't need to have the headers
declared), it's still sensible to have a common type for all subtypes that have the headers
property.
很明显,headers
属性的声明对某些类型(如 Foo
和 Bar
)是通用的,但是,如果在 IFoo
中声明它没有意义(出于代码设计原因,例如其他类型的 IFoo
不需要声明 headers
),仍然有必要为具有 headers
属性的所有子类型创建一个通用类型。
In Dart, using mixin would be a proper way to achieve it. Example:
在Dart中,使用 mixin 是实现这一目标的合适方式。示例:
abstract class IFoo {}
抽象类 IFoo {}
mixin MixinFoo {
String get headers => 'MixinFoo';
}
mixin MixinFoo {
String get headers => 'MixinFoo';
}
class Foo with MixinFoo implements IFoo {
@override
String get headers => 'Foo';
}
class Foo with MixinFoo implements IFoo {
@override
String get headers => 'Foo';
}
class Bar with MixinFoo implements IFoo {
@override
String get headers => 'Bar';
}
class Bar with MixinFoo implements IFoo {
@override
String get headers => 'Bar';
}
Note that Foo
and Bar
are still IFoo
types, additionally, they are MixinFoo
as well! This means that they have the headers
property without mixing the logic of being IFoo
s.
请注意,Foo
和 Bar
仍然是 IFoo
类型,此外,它们还是 MixinFoo
!这意味着它们具有 headers
属性,而无需混合成为 IFoo
的逻辑。
Therefore, you are able to cast the given value, as:
因此,您可以将给定的值转换为:
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) {
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;
}
}
Or (since we are talking about an "elegant way" 😄):
或者(因为我们正在谈论一种“优雅的方法” 😄):
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...
}
}
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...
}
}
Any MixinFoo type will be castable now, it makes more sense from a code design perspective.
现在任何 MixinFoo 类型都可以进行转换,从代码设计的角度来看,这更有意义。
英文:
> Is there a more elegant way than the above first example?
Taking a look at a higher level of the whole picture, the "elegant way" that I'd suggest in this case is following the Interface Segregation Principle.
It's clear that the declaration of the headers
property is common for some of the types (such as Foo
and Bar
), however, if declaring it in IFoo
does not make sense (for code design reasons, such as there are other types of IFoo
don't need to have the headers
declared), it's still sensible to have a common type for all subtypes that have the headers
property.
In Dart, using mixin would be a proper way to achieve it. Example:
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';
}
Note that Foo
and Bar
are still IFoo
types, additionally, they are MixinFoo
as well! This means that they have the headers
property without mixing the logic of being IFoo
s.
Therefore, you are able to cast the given value, as:
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;
}
}
Or (since we are talking about an "elegant way" 🙂):
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...
}
}
Any MixinFoo
type will be castable now, it makes more sense from a code design perspective.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论