Ответ 1
Нет, С# не поддерживает утиную печать.
Подход OOP к этой проблеме состоит в том, чтобы использовать шаблон адаптера.
Вы бы сделали это:
class FooBarAdapter : IBar {
private readonly Foo foo;
public FooBarAdapter(Foo foo) {
this.foo = foo;
}
public void Go() {
this.foo.Go();
}
}
Всякий раз, когда у вас есть Foo
, но требуется IBar
, вы завершаете его по запросу:
public void ContrivedScenario() {
Foo foo = GetFooFromExternalDependency();
FooBarAdapter adapter = new FooBarAdapter( foo );
this.NeedsIBar( adapter );
}
public void NeedsIBar(IBar bar) { ... }
Хочу отметить, что если Foo
-До- IBar
преобразование происходит много, вы можете использовать неявные преобразования, так что вам не нужно явно построить FooBarAdapter
экземпляры, но это спорно, если это хорошая практика разработки программного обеспечения или нет:
class FooBarAdapter : IBar {
// (same as above)
public static implicit operator FooBarAdapter(Foo foo) {
return new FooBarAdapter( foo );
}
}
Таким образом вы можете сделать это:
public void ContrivedScenario() {
Foo foo = GetFooFromExternalDependency();
this.NeedsIBar( foo ); // the conversion from `Foo foo` to `FooBarAdapter` happens implicitly
}
Одна из причин, почему С# не поддерживает утиную настройку, состоит в том, что только потому, что интерфейс класса (в смысле ООП, а не буквальный interface
) имеет те же идентификаторы, что и другие, не означает, что они совместимы. Например, Process.Kill
(убивает процесс) и MegaDeathKillBot3000.Kill
(убивает все человечество), вероятно, не следует использовать взаимозаменяемо... если вы действительно этого не хотите.