Использование для множественного наследования?

Вы можете использовать несколько методов для этой проблемы, например

  1. Использование line-height
    #wrapper {  line-height: 0px;  }
    
  2. Использование display: flex
    #wrapper {  display: flex;         }
    #wrapper {  display: inline-flex;  }
    
  3. Используя display: block, table, flex и inherit
    #wrapper img {  display: block;    }
    #wrapper img {  display: table;    }
    #wrapper img {  display: flex;     }
    #wrapper img {  display: inherit;  }
    
21
задан RS Conley 23 February 2009 в 20:50
поделиться

12 ответов

Большая часть использования Множественного наследования полного масштаба для mixins. Как пример:

class DraggableWindow : Window, Draggable { }
class SkinnableWindow : Window, Skinnable { }
class DraggableSkinnableWindow : Window, Draggable, Skinnable { }

и т.д.

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

class DraggableWindow : Window, IDraggable { }

Тогда Вы реализуете интерфейс IDraggable в своем классе DraggableWindow. Слишком трудно записать хорошие классы смешивания.

преимущество подхода MI (даже если Вы только используете Интерфейсный MI) - то, что можно тогда рассматривать все виды другого Windows как Объекты окна, но иметь гибкость для создания вещей, которые не были бы возможными (или более трудными) с единичным наследованием.

, Например, во многих платформах класса Вы видите что-то вроде этого:

class Control { }
class Window : Control { }
class Textbox : Control { }

Теперь, предположите желание Текстового поля с характеристиками Окна? Как то, чтобы быть перемещаемым, имея строку заголовка, и т.д... Вы могли сделать что-то вроде этого:

class WindowedTextbox : Control, IWindow, ITexbox { }

В модели единичного наследования, Вы не можете легко наследоваться и Окну и Текстовому полю, не имея некоторых проблем с дублирующимися Объектами управления и другими видами проблем. Можно также рассматривать WindowedTextbox как Окно, Текстовое поле или Управление.

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

29
ответ дан 29 November 2019 в 06:38
поделиться

Я нахожу множественное наследование особенно полезным при использовании смешивание классы.

, Как указано в Википедии:

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

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

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

пример множественного наследования:

class Animal
{
   virtual void KeepCool() const = 0;
}

class Vertebrate
{
   virtual void BendSpine() { };
}


class Dog : public Animal, public Vertebrate
{
   void KeepCool() { Pant(); }
}

то, Что является самым важным при выполнении любой формы общедоступного наследования (единственный или несколько) должно уважать эти , отношения. Класс должен только наследоваться одному или нескольким классам, если это "-" один из тех объектов. Если это просто "содержит" один из тех объектов, агрегирование или состав должны использоваться вместо этого.

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

13
ответ дан 29 November 2019 в 06:38
поделиться

Большинство людей использует множественное наследование в контексте применения несколько интерфейсов к классу. Это - Java подхода, и C#, среди других, осуществляют.

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

Другое использование, как LeopardSkinPillBoxHat указывает , находится в соединении-ins. Превосходный пример этого библиотека Loki из книги Andrei Alexandrescu современный Дизайн C++. Он использует то, что он называет занятия по политике , которые определяют поведение или требования данного класса посредством наследования.

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

использование для MI - многие. Потенциал для злоупотребления еще больше.

4
ответ дан 29 November 2019 в 06:38
поделиться

Java имеет интерфейсы. C++ не имеет.

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

4
ответ дан 29 November 2019 в 06:38
поделиться

Я думаю, что это было бы самым полезным для шаблонного кода. Например, шаблон IDisposable является точно тем же для всех классов в.NET. Итак, почему перепечатывают тот код много раз?

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

, К сожалению, множественным наследованием очень легко злоупотребить. Люди быстро начнут делать, глупые вещи как класс LabelPrinter наследовались своему классу TcpIpConnector вместо, просто содержат его.

3
ответ дан 29 November 2019 в 06:38
поделиться

Один случай я работал над недавно включенной сетью, включил принтеры маркировки. Мы должны распечатать маркировки, таким образом, у нас есть класс LabelPrinter. Этот класс имеет виртуальные вызовы для печати нескольких различных маркировок. У меня также есть универсальный класс для соединенных вещей TCP/IP, которые могут соединиться, отправить и получить. Так, когда я должен был реализовать принтер, он наследовался и классу LabelPrinter и классу TcpIpConnector.

2
ответ дан 29 November 2019 в 06:38
поделиться

Я думаю, что fmsf примером является плохая идея. Автомобиль не является шиной или механизмом. Необходимо использовать состав для этого.

миля (реализации или интерфейса) может использоваться для добавления функциональности. Их часто называют, смешивая классы.. Предположите, что у Вас есть GUI. Существует класс представления, который обрабатывает рисунок и Drag& класс Отбрасывания, который обрабатывает перетаскивание. Если бы у Вас есть объект, который делает обоих, которых у Вас был бы класс как

class DropTarget{
 public void Drop(DropItem & itemBeingDropped);
...
}

class View{
  public void Draw();
...
}

/* View you can drop items on */
class DropView:View,DropTarget{

}
2
ответ дан 29 November 2019 в 06:38
поделиться

Это верно, что состав интерфейса (Java или C# как) плюс передача помощнику может эмулировать многое из общего использования множественного наследования (особенно mixins). Однако это сделано за счет того передающего повторяемого кода (и нарушающий DRY).

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

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

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

1
ответ дан 29 November 2019 в 06:38
поделиться

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

Этот пример действительно не иллюстрирует полноценность множественного наследования. Каким быть определенным здесь является ИНТЕРФЕЙС. Множественное наследование позволяет Вам наследовать поведение также. Который является точкой mixins.

пример; из-за потребности сохранить назад совместимость я должен реализовать свои собственные методы сериализации.

, Таким образом, каждый объект получает метод Чтения и Хранилища как это.

Public Sub Store(ByVal File As IBinaryWriter)
Public Sub Read(ByVal File As IBinaryReader)

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

Public Sub Assign(ByVal tObject As <Class_Name>)
Public Function Clone() As <Class_Name>

Теперь в VB6 у меня есть этот код, повторенный много раз.

Public Assign(ByVal tObject As ObjectClass)
    Me.State = tObject.State
End Sub

Public Function Clone() As ObjectClass
    Dim O As ObjectClass
    Set O = New ObjectClass
    O.State = Me.State
    Set Clone = 0
End Function

Public Property Get State() As Variant
    StateManager.Clear
    Me.Store StateManager
    State = StateManager.Data
End Property

Public Property Let State(ByVal RHS As Variant)
    StateManager.Data = RHS
    Me.Read StateManager
End Property

Примечание, что Statemanager является потоком, которые читают и хранят массивы байтов.

Этот код является повторенными десятками времен.

Теперь в.NET я в состоянии обойти это при помощи комбинации дженериков и наследования. Мой объект под версией.NET добирается, Присваиваются, Клон и состояние, когда они наследовались MyAppBaseObject. Но мне не нравится то, что каждый объект наследовался MyAppBaseObject.

я скорее просто смешиваюсь в интерфейс Assign Clone И ПОВЕДЕНИЕ. Еще лучше соединение в отдельно интерфейсе Read и Store тогда способность смешаться в Присваивается и Клон. Это был бы более чистый код, по-моему.

, Но времена, где я снова использую поведение, ЗАТМЕВАЮТСЯ к тому времени, когда я использую Интерфейс. Это вызвано тем, что цель большинства иерархий объектов не о многократном использовании поведения, но точно определении отношений между различными объектами. Для которого разработаны интерфейсы. Таким образом, в то время как было бы хорошо, что C# (или VB.NET) имел некоторую способность сделать это, это не выставочный стопор, по-моему.

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

Позже идея mixins (и другие связанные понятия в аспектно-ориентированном программировании) были разработаны. Множественное наследование было найдено полезным в создании соединения-ins. Но C# был разработан непосредственно перед тем, как это было широко распознано. Вероятно, альтернативный синтаксис будет разработан, чтобы сделать это.

1
ответ дан 29 November 2019 в 06:38
поделиться

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

миля является еще одним из тех, 'используют его, если Вы ДЕЙСТВИТЕЛЬНО нуждаетесь в нем, но удостоверяетесь, что Вам ДЕЙСТВИТЕЛЬНО нужен он' инструменты.

1
ответ дан 29 November 2019 в 06:38
поделиться

Следующий пример - главным образом что-то, что я часто вижу в C++: иногда это может быть необходимо из-за служебных классов, в которых Вы нуждаетесь, но из-за их дизайна не может использоваться через состав (по крайней мере, не эффективно или не делая код еще более грязным, чем возвращение mult. наследование). Хороший пример - Вы, имеют абстрактный базовый класс A и производный класс B, и B также должен быть своего рода сериализуемым классом, таким образом, он должен произойти из, скажем, другой абстрактный класс, названный сериализуемым. Возможно избежать MI, но, если сериализуемый только содержит несколько виртуальных методов и нуждается в глубоком доступе к членам парламента, не занимающим официального поста B, тогда может стоить пачкать дерево наследования только, чтобы не подружиться объявления и выдать доступ к внутренностям B к некоторому классу состава помощника.

0
ответ дан 29 November 2019 в 06:38
поделиться

I had to use it today, actually...

Here was my situation - I had a domain model represented in memory where an A contained zero or more Bs(represented in an array), each B has zero or more Cs, and Cs to Ds. I couldn't change the fact that they were arrays (the source for these arrays were from automatically generated code from the build process). Each instance needed to keep track of which index in the parent array they belonged in. They also needed to keep track of the instance of their parent (too much detail as to why). I wrote something like this (there was more to it, and this is not syntactically correct, it's just an example):

class Parent
{
    add(Child c)
    {
        children.add(c);
        c.index = children.Count-1;
        c.parent = this;
    }
    Collection<Child> children
}

class Child
{
    Parent p;
    int index;
}

Then, for the domain types, I did this:

class A : Parent
class B : Parent, Child
class C : Parent, Child
class D : Child

The actually implementation was in C# with interfaces and generics, and I couldn't do the multiple inheritance like I would have if the language supported it (some copy paste had to be done). So, I thought I'd search SO to see what people think of multiple inheritance, and I got your question ;)

I couldn't use your solution of the .anotherClass, because of the implementation of add for Parent (references this - and I wanted this to not be some other class).

It got worse because the generated code had A subclass something else that was neither a parent or a child...more copy paste.

0
ответ дан 29 November 2019 в 06:38
поделиться