Как повторно использовать код, когда множественное наследование не вариант? - PullRequest
2 голосов
/ 30 июля 2009

Я хотел бы использовать несколько методов из пары моих старых протестированных классов в мой новый класс, который я строю. К сожалению, C # не поддерживает множественное наследование. Как я могу использовать код из этих старых классов? Я просто создаю их как объекты-члены? или у меня есть другие варианты?

Ответы [ 6 ]

11 голосов
/ 30 июля 2009

Как правило, использование композиции вместо наследования - это путь вперед, да. Если бы вы могли привести конкретный пример того, что вы имеете в виду, это облегчило бы поиск подходящего подхода: он не всегда одинаков.

4 голосов
/ 30 июля 2009

Вы можете воссоздать их как методы расширения, если они работают с одним и тем же типом.

public static void MyMethod( this MyType target ){}


MyType.MyMethod()

как отмечено ниже, если у вас есть класс, производный от MyType или более распространенный реализующий интерфейс, на котором работает метод расширения, расширение работает для них.

public class MyDerived : MyType{}

MyDerived.MyMethod()
4 голосов
/ 30 июля 2009

Использование их в качестве объектов-членов должно быть хорошей идеей. Тогда вы также можете выставить только интересующие вас методы и адаптировать их при необходимости.

2 голосов
/ 30 июля 2009

Технически, C # реализует множественное интерфейс наследование, но не множественное реализация наследование.

Проблема с множественным наследованием реализации заключается в том, что оно приводит к такие ситуации, как проблема алмазов .

Вы можете моделировать множественное наследование реализации, используя несколько интерфейсов. наследственность и состав, который близок к тому, что вы описали как создание объекты, которые вы хотите повторно использовать "в качестве объектов-членов". Чего ты не хочешь чтобы сделать, однако, выставить ненужное поведение от вашего упакованного типа.

Ниже приведена диаграмма классов, показывающая основной принцип множественного наследование по составу:

Множественное наследование http://www.freeimagehosting.net/uploads/cb219cefba.jpg

Недостатком этого является то, что любые изменения интерфейса IBreeper потребуют соответствующие изменения в Breeper, и наоборот.

Делая шаг назад - вам нужно внимательно изучить причины сочинять старые классы. Это к:

  1. Улучшение или усиление существующего поведения. Затем вы должны рассмотреть Proxy Pattern ;

  2. Создайте "универсальный магазин" для всего вашего поведения. Вы действительно должны делать это только в том случае, если ваш SuperFuddler является связным (то есть все выставленное поведение выровнено), в противном случае вы перейдете в Объект Бога ситуация, которая не способствует тому, чтобы ее можно было обслуживать;

  3. Представьте интерфейс, который больше соответствует режиму использования, необходимому для определенного класса клиентов вашего SuperFuddler. В этом случае вы должны рассмотреть Pattern Adapter .

0 голосов
/ 30 июля 2009

Вы можете легко подделать это так:

public interface IFoo {
    void DoFoo();
}

public class Foo : IFoo {
    public void DoFoo() { Console.Write("Foo"); }
}

public class Bar {
    public void DoBar() { Console.Write("Bar"); }
}

public class FooBar : IFoo, Bar {
    private IFoo baseFoo = new Foo();
    public void DoFoo() { baseFoo.DoFoo(); }
}

//...

FooBar fooBar = new FooBar();

fooBar.DoFoo();
fooBar.DoBar();
0 голосов
/ 30 июля 2009

если вы разработали их как компонент, используйте их, не наследуйте от них

...