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

huangapple go评论61阅读模式
英文:

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
FooBar 都实现了 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 属性的声明对某些类型(如 FooBar)是通用的,但是,如果在 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 IFoos.

请注意,FooBar 仍然是 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 IFoos.

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.

huangapple
  • 本文由 发表于 2023年6月12日 21:55:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76457377.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定