C# должен иметь множественное наследование? [закрытый]

54
задан 7 revs, 6 users 95% 11 November 2012 в 09:58
поделиться

33 ответа

Я никогда не пропускал его однажды, не никогда. Да, это [MI] сложно, и да, интерфейсы делают подобное задание во многих отношениях - но это не самая большая точка: в общем смысле это просто не необходимо большую часть времени. Даже единичное наследование злоупотребляется во многих случаях.

113
ответ дан 2 revs 7 November 2019 в 07:34
поделиться

Я отправил это здесь пару раз, но я просто думаю, что это действительно прохладно. Можно изучить, как фальсифицировать MI здесь . Я также думаю выделения статьи, почему MI является такой болью, даже если это не было предназначено.

я никакая мисс это или потребность это, я предпочитаю использовать состав объектов достичь моих целей. Это - действительно точка статьи также.

1
ответ дан Flory 7 November 2019 в 07:34
поделиться

Я использовал несколько наследование в C++ сам также, но действительно необходимо знать то, что Вы делаете для не получения в проблеме, особенно если у Вас есть два базовых класса, которые совместно используют прародителя. Тогда можно войти в проблемы с виртуальным наследованием, имея необходимость объявить каждого конструктора, Вы собираетесь раскритиковать цепочку (который делает двоичное повторное использование намного тяжелее)..., это может быть путаницей.

, Что еще более важно, способ, которым в настоящее время создается CLI, устраняет MI от того, чтобы быть реализованным легко . Я уверен, что они могли сделать это, если бы они хотели, но у меня есть другие вещи, я видел бы в CLI, чем нескольких наследование.

Вещи, которые я хотел бы видеть, включают некоторые функции Spec#, как не допускающие NULL-значения ссылочные типы. Я также хотел бы видеть больше объектной безопасности способностью объявить параметры как константу и способность объявить функциональную константу (подразумевать, что Вы гарантируете, что внутреннее состояние объекта не будет изменено методом, и компилятор проверяет Вас дважды).

я думаю, что между Единственным Inheritence, Несколько Интерфейсный Inheritence, Дженерики, и Дополнительными Методами, можно сделать в значительной степени что-либо, что Вы должны. Если бы что-нибудь могло бы улучшить вещи для кого-то требующего MI, я думаю своего рода конструкция языка, которая была бы позволять более легкое агрегирование, и состав необходим. Тем путем Вы можете иметь общий интерфейс, но тогда делегировать Вашу реализацию к частному экземпляру класса, которому Вы обычно наследовались бы. Прямо сейчас это берет много шаблонного кода, чтобы сделать. Наличие более автоматизированной функции языка этого значительно помогло бы.

1
ответ дан Nick 7 November 2019 в 07:34
поделиться

Я предпочитаю C++. Я использовал Java, C#, и т.д. Поскольку мои программы становятся более сложными в такой среде OO, я пропускаю Множественное наследование. Это - мой субъективный опыт.

Это может сделать для удивительного запутанного кода..., это может сделать для удивительно изящного кода.

1
ответ дан Paul Nathan 7 November 2019 в 07:34
поделиться

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

Вы принимаете решение использовать тех API, который уже записал разработчик, Вы не имеете также.

1
ответ дан Signal9 7 November 2019 в 07:34
поделиться

Дайте C# implicits, и Вы не пропустите множественное наследование или любое наследование в этом отношении.

1
ответ дан Apocalisp 7 November 2019 в 07:34
поделиться

Нет я не делаю. Я использую все другие функции OO для разработки то, что я хочу. Я использую Интерфейсную и объектную инкапсуляцию, и я никогда не ограничиваюсь на том, что я хочу сделать.

1
ответ дан Patrick Desjardins 7 November 2019 в 07:34
поделиться

Я думаю его простое действительно. Точно так же, как любая другая сложная парадигма программирования можно неправильно использовать его и причинить себе боль. Можете Вы неправильно использовать объекты (ах да!), но это не означает, что OO плохо сам по себе.

Так же с MI. Если у Вас не будет большого 'дерева' наследованных классов или большого количества классов, которые предоставляют те же именованные методы, то Вы будете совершенно здоровы с MI. На самом деле, поскольку MI обеспечивает реализацию, Вы часто будете более обеспечены, чем реализация SI, где необходимо повторно кодировать, или cut& методы вклеивания для делегированных объектов. Меньше кода лучше в этих случаях.. можно сделать всемогущую путаницу из совместного использования кода путем попытки снова использовать объекты посредством интерфейсного наследования. И такие обходные решения не пахнут правильными.

я думаю, что модель единичного наследования.NET испорчена: они должны были пойти с интерфейсами только или MI только. Наличие "половины и половины" (т.е. единственное наследование реализации плюс несколько соединяют интерфейсом с наследованием) более сбивает с толку, чем это должно быть, и не изящно вообще.

я происхожу из среды MI, и я не боюсь или записан ею.

1
ответ дан gbjbaanb 7 November 2019 в 07:34
поделиться

Я пытаюсь не использовать наследование. Меньше я могу каждый раз.

1
ответ дан Pokus 7 November 2019 в 07:34
поделиться

Нет, мы ушли от него. Вам действительно нужен он теперь.

1
ответ дан 2 revs, 2 users 67% 7 November 2019 в 07:34
поделиться

Коллега записал этот блог о том, как получить что-то как множественное наследование в C# с Динамической компиляцией:

http://www.atalasoft.com/cs/blogs/stevehawley/archive/2008/09/29/late-binding-in-c-using-dynamic-compilation.aspx

1
ответ дан Lou Franco 7 November 2019 в 07:34
поделиться

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

1
ответ дан coder1 7 November 2019 в 07:34
поделиться

Вместо множественного наследования можно использовать mixins, который является лучшим решением.

2
ответ дан 2 revs 7 November 2019 в 07:34
поделиться

Я привел бы доводы против множественного наследования просто по причине, которую Вы заявляете. Разработчики будут неправильно использовать его. Я видел достаточно проблем с каждым классом, наследовавшимся служебному классу, именно так можно вызвать функцию от каждого класса, не будучи должен ввести так много, знать, что множественное наследование привело бы к плохому коду во многих ситуациях. То же самое могло быть сказано о GoTo, который является одной из причин, это - использование, так осужден. Я думаю, что множественное наследование действительно имеет некоторое хорошее использование, точно так же, как GoTo, В идеальном мире, где они оба только использовались, когда соответственно, не будет никаких проблем. Однако мир не идеален, таким образом, мы должны защитить плохих программистов от себя.

5
ответ дан Kibbee 7 November 2019 в 07:34
поделиться

(для голосования)

2
ответ дан CrashCodes 7 November 2019 в 07:34
поделиться

один из действительно хороших и (в то время) новые вещи о DataFlex 4GL v3 + (я знаю, я знаю, Данные что ?) была его поддержка смешивание наследование - методы от любых других классов могли быть снова использованы в Вашем классе; пока Ваш класс обеспечил свойства, которые использовали эти методы, он работал просто великолепно, и не было никакой "ромбовидной проблемы" или другого множественного наследования "глюки" для волнения о.

я хотел бы видеть что-то вроде этого в C#, поскольку он упростит определенные виды абстракции и проблем конструкции

2
ответ дан Steven A. Lowe 7 November 2019 в 07:34
поделиться

Обновление
я бросаю вызов всем, кто проваливает меня, чтобы показать мне любой пример множественного наследования, что я не могу легко портировать на язык с единичным наследованием. Если любой не может показать никакой подобный образец, я утверждаю, что он не существует. Я портировал тонны кода C++ (MH) к Java (без MH), и это никогда не было проблемой, неважно, сколько MH код C++ использовал.

<час>

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

На самом деле множественным наследованием обычно злоупотребляют. Если Вы используете дизайн OO для, так или иначе моделируют реальный мир в классы, Вы никогда не будете переходить к сути дела, где множественное наследование имеет на самом деле смысл. Можно ли обеспечить полезный пример для множественного наследования? Большинство примеров, которые я видел до сих пор, является на самом деле "неправильным". Они делают что-то подклассом, который является на самом деле просто дополнительным свойством и таким образом на самом деле интерфейсом.

Смотрят на Sather. Это - язык программирования, где интерфейсы имеют множественное наследование, как, почему не (это не может создать ромбовидную проблему), однако классы, которые не являются никакими интерфейсами, не имеют никакого наследования вообще. Они могут только реализовать интерфейсы, и они могут "включать" другие объекты, который делает эти другие объекты фиксированной частью их, но это не то же как наследование, это - скорее форма делегации (вызовы метода, "наследованные" включением объектов, на самом деле просто передаются экземплярам этих объектов, инкапсулировавших в Вашем объекте). Я думаю, что это понятие довольно интересно, и оно показывает, что у Вас может быть полный чистый язык OO без любого наследования реализации вообще.

2
ответ дан 2 revs 7 November 2019 в 07:34
поделиться

Множественное наследование в целом может быть полезным, и много языков OO реализуют его так или иначе (C++, Eiffel, CLOS, Python...). Действительно ли это важно? Нет. Действительно ли хорошо иметь? Да.

2
ответ дан Nemanja Trifunovic 7 November 2019 в 07:34
поделиться

Я работал с C#, так как это было сначала доступно как альфа/бета-версия и никогда не пропускало множественное наследование. MI хорош для некоторых вещей, но существуют почти всегда другие способы достигнуть того же результата (некоторые из которых на самом деле заканчивают тем, что были более простыми или создали более легкое для понимания реализации).

2
ответ дан Scott Dorman 7 November 2019 в 07:34
поделиться

Я рад, что C# не имеет Множественного наследования, даже при том, что это иногда было бы удобно. Что я хотел бы видеть, вместо этого способность обеспечить реализацию по умолчанию метода интерфейса. Это:

interface I
{
    void F();
    void G();
}


class DefaultI : I
{
    void F() { ... }
    void G() { ... }
}

class C : I = DefaultI
{
    public void F() { ... } // implements I.F
}

В этом случае, ((I)new C()).F() будет звонить C реализация I.F(), в то время как ((I)new C()).G() будет звонить DefaultI реализация I.G().

существует много проблем, которые должны были бы разработать разработчики языка, прежде чем это могло быть добавлено к языку, но ни один, что очень твердо, и результат, не удовлетворил бы многие потребности, которые делают Множественное наследование желательным.

3
ответ дан Jay Bazuzi 7 November 2019 в 07:34
поделиться

ДА! ДА! и ДА!

Серьезно, я разрабатывал библиотеки GUI моя вся карьера, и MI (Множественное наследование) делает настолько далеко легче, чем SI (Единичное наследование)

Первый, я сделал SmartWin ++ в C++ (MI, в большой степени используемый) тогда, я сделал Gaia Ajax и наконец теперь Ajax Ра , и я могу с экстремальным уверенным государством, которым MI управляет для некоторых мест. Одно из тех мест, являющихся библиотеками GUI...

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

Точно так же, как языки функционального программирования (как Lisp) преподавались ("non-Lispers") как "слишком сложные" нефункциональными защитниками языка программирования...

Люди боятся неизвестного...

ПРАВИЛА МИЛИ!

5
ответ дан Thomas Hansen 7 November 2019 в 07:34
поделиться

Я думаю, что это сверхусложнило бы вещи, не обеспечивая достаточно ROI. Мы уже видим людей код.NET мясника с также глубокими деревьями наследования. Я могу просто вообразить злодеяния, если люди имели право делать множественное наследование.

я не отклоню это, это имеет потенциал, но я просто не вижу достаточного преимущества.

1
ответ дан Bob King 7 November 2019 в 07:34
поделиться

Я на самом деле пропускаю множественное наследование по одной определенной причине... расположить шаблон.

КАЖДЫЙ раз, когда я должен реализовать расположить шаблон, я говорю мне: "Мне бы хотелось просто произойти из класса, который реализует расположить шаблон с несколькими виртуальными переопределениями". Я копирую и вставляю тот же шаблонный код в каждый класс, который реализует IDispose, и я ненавижу его.

7
ответ дан Brian Genisio 7 November 2019 в 07:34
поделиться

Множественное наследование не поддерживается CLR всегда, я знаю, таким образом, я сомневаюсь, что это могло поддерживаться эффективным способом, как это находится в C++ (или Eiffel, который может сделать это лучше, учитывая, что язык специально предназначен для MI).

А хорошую альтернативу Множественному наследованию называют Чертами. Это позволяет Вам смешивать вместе различные единицы поведения в единый класс. Компилятор может поддерживать черты как расширение времени компиляции системы типов единичного наследования. Вы просто объявляете, что класс X включает черты A, B, и C, и компилятор помещает черты, которые Вы просите вместе формировать реализацию X.

, Например, предполагать, что Вы пытаетесь реализовать IList (T). Если Вы смотрите на различные реализации IList (T), они часто совместно используют часть того же самого кода. Это, были черты, входят. Вы просто объявляете черту с общим кодом в нем, и можно использовать тот общий код в любой реализации IList (T) - даже если реализация уже имеет некоторый другой базовый класс. Вот то, на что мог бы быть похожим синтаксис:

/// This trait declares default methods of IList<T>
public trait DefaultListMethods<T> : IList<T>
{
    // Methods without bodies must be implemented by another 
    // trait or by the class
    public void Insert(int index, T item);
    public void RemoveAt(int index);
    public T this[int index] { get; set; }
    public int Count { get; }

    public int IndexOf(T item)
    {
        EqualityComparer<T> comparer = EqualityComparer<T>.Default;
        for (int i = 0; i < Count; i++)
            if (comparer.Equals(this[i], item))
                return i;
        return -1;
    }
    public void Add(T item)
    {
        Insert(Count, item);
    }
    public void Clear()
    {   // Note: the class would be allowed to override the trait 
        // with a better implementation, or select an 
        // implementation from a different trait.
        for (int i = Count - 1; i >= 0; i--)
            RemoveAt(i);
    }
    public bool Contains(T item)
    {
        return IndexOf(item) != -1;
    }
    public void CopyTo(T[] array, int arrayIndex)
    {
        foreach (T item in this)
            array[arrayIndex++] = item;
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(T item)
    {
        int i = IndexOf(item);
        if (i == -1)
            return false;
        RemoveAt(i);
        return true;
    }
    System.Collections.IEnumerator 
        System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < Count; i++)
            yield return this[i];
    }
}

И Вы используете черту как это:

class MyList<T> : MyBaseClass, DefaultListMethods<T>
{
    public void Insert(int index, T item) { ... }
    public void RemoveAt(int index)       { ... }
    public T this[int index] {
        get { ... }
        set { ... }
    }
    public int Count {
        get { ... }
    }
}

, Конечно, я просто царапаю поверхность здесь. Для большего количества полного описания посмотрите бумагу Черты: Компонуемые Единицы Поведения (PDF).

язык Ржавчины (от Mozilla) реализовал Черты интересным способом: они заметили, что черты подобны интерфейсным реализациям по умолчанию, таким образом, они объединили интерфейсы и черты в единственную функцию (который они называют чертами). Основное различие между чертами и значением по умолчанию соединяет интерфейсом с реализациями (который Java теперь имеет), то, что черты могут содержать закрытые или защищенные методы, в отличие от традиционных методов интерфейса, которые должны быть общедоступными. Если черты и интерфейсы не объединены в единственную функцию, то другое различие - то, что у Вас может быть ссылка на интерфейс, но у Вас не может быть ссылки на черту; черта не является самостоятельно типом.

8
ответ дан 5 revs 7 November 2019 в 07:34
поделиться

C# поддерживает единичное наследование, интерфейсы и дополнительные методы. Между ними они обеспечивают примерно все, что множественное наследование обеспечивает без головных болей, которые приносит множественное наследование.

12
ответ дан David Arno 7 November 2019 в 07:34
поделиться

Вот очень полезный случай для множественного наследования, что я сталкиваюсь со всем временем.

, Поскольку поставщик инструментария, которого я не могу изменить, опубликовал API, или я буду повреждать назад совместимость. Одна вещь, которая следует, который является, что я никогда не могу добавлять к интерфейсу, как только я выпустил ее, потому что она повредила бы компиляцию для любого реализующего его - единственная опция, состоит в том, чтобы расширить интерфейс.

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

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

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

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

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

15
ответ дан Lou Franco 7 November 2019 в 07:34
поделиться

Предпочтите агрегирование по наследованию!

class foo : bar, baz

часто лучше обрабатывается с

class foo : Ibarrable, Ibazzable
{
  ... 
  public Bar TheBar{ set }
  public Baz TheBaz{ set }

  public void BarFunction()
  {
     TheBar.doSomething();
  }
  public Thing BazFunction( object param )
  {
    return TheBaz.doSomethingComplex(param);
  }
}

Этот способ, которым можно загрузить и различные реализации IBarrable и IBazzable для создания нескольких версий Приложения, не имея необходимость писать еще один класс.

Внедрение зависимости может помочь с этим много.

37
ответ дан 3 revs, 2 users 98% 7 November 2019 в 07:34
поделиться

Одной из проблем с контактом со множественным наследованием является различие между интерфейсным наследованием наследования и реализации.

C# уже имеет чистую реализацию интерфейсного наследования (включая выбор неявных или явных реализаций) при помощи чистых интерфейсов.

при рассмотрении C++, для каждого класса Вы определяете после двоеточия в class объявление, вид наследования, которое Вы получаете, определяется модификатором доступа (private, protected, или public). С public наследование, Вы получаете полный беспорядок нескольких inheritance— несколько интерфейсов смешаны с несколькими реализациями. С private наследование, Вы просто получаете реализацию. Объект" class Foo : private Bar" никогда не может передаваться функции, которая ожидает Bar, потому что это - как будто Foo класс действительно просто имеет частное Bar поле и автоматически реализованный делегация шаблон .

Чистый несколько наследование реализации (который является действительно просто автоматической делегацией) не представляет проблем и было бы потрясающе иметь в C#.

Что касается нескольких соединяют интерфейсом с наследованием от классов, существует много различных возможных проектов для того, чтобы реализовать опцию. Каждый язык, который имеет множественное наследование, имеет свои собственные правила относительно того, что происходит, когда метод называют с тем же именем в нескольких базовых классах. Некоторые языки, как язык Common LISP (особенно система объекта CLOS), и Python, имеют протокол метаобъекта, где можно определить приоритет базового класса.

Вот одна возможность:

abstract class Gun
{ 
    public void Shoot(object target) {} 
    public void Shoot() {}

    public abstract void Reload();

    public void Cock() { Console.Write("Gun cocked."); }
}

class Camera
{ 
    public void Shoot(object subject) {}

    public virtual void Reload() {}

    public virtual void Focus() {}
}

//this is great for taking pictures of targets!
class PhotoPistol : Gun, Camera
{ 
    public override void Reload() { Console.Write("Gun reloaded."); }

    public override void Camera.Reload() { Console.Write("Camera reloaded."); }

    public override void Focus() {}
}

var    pp      = new PhotoPistol();
Gun    gun     = pp;
Camera camera  = pp;

pp.Shoot();                    //Gun.Shoot()
pp.Reload();                   //writes "Gun reloaded"
camera.Reload();               //writes "Camera reloaded"
pp.Cock();                     //writes "Gun cocked."
camera.Cock();                 //error: Camera.Cock() not found
((PhotoPistol) camera).Cock(); //writes "Gun cocked."
camera.Shoot();                //error:  Camera.Shoot() not found
((PhotoPistol) camera).Shoot();//Gun.Shoot()
pp.Shoot(target);              //Gun.Shoot(target)
camera.Shoot(target);          //Camera.Shoot(target)

В этом случае, только реализация первого перечисленного класса неявно наследована в случае конфликта. Класс для других базовых типов должен быть явно определен для достигания их реализаций. Для создания его более защищенным от дурака компилятор может запретить неявное наследование в случае конфликта (конфликтующие методы всегда требовали бы броска).

кроме того, можно реализовать множественное наследование в C# сегодня с неявными операторами преобразования:

public class PhotoPistol : Gun /* ,Camera */
{
    PhotoPistolCamera camera;

    public PhotoPistol() {
        camera = new PhotoPistolCamera();
    }

    public void Focus() { camera.Focus(); }

    class PhotoPistolCamera : Camera 
    { 
        public override Focus() { }
    }

    public static Camera implicit operator(PhotoPistol p) 
    { 
        return p.camera; 
    }
}

Это не прекрасно, тем не менее, поскольку это не поддерживается is и as операторы, и System.Type.IsSubClassOf().

25
ответ дан 5 revs, 3 users 69% 7 November 2019 в 07:34
поделиться

Если мы введем множественное наследование, то мы снова столкнемся со старой проблемой Diamond C ++ ...

Однако для тех, кто думает, что это неизбежно, мы все еще можем ввести эффекты множественного наследования с помощью композиции (Составьте несколько объектов в объекте и предоставьте открытые методы, которые делегируют ответственность составному объекту и возвращают) ...

Так зачем беспокоиться о множественном наследовании и делать свой код уязвимым для неизбежных исключений ...

0
ответ дан 7 November 2019 в 07:34
поделиться

Нет, пока проблема Diamond не будет решена. и вы можете использовать композицию, пока это не будет решено.

1
ответ дан 7 November 2019 в 07:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: