Множественное наследование? - PullRequest
9 голосов
/ 16 февраля 2012

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

Мой конкретный случай касается Активов и различных типов Активов.

Начиная с Актив ...

Каждый PhysicalDevice является Активом
Каждый VirtualDevice является Актив
Каждый Сервер является Активом

Каждый PhysicalServer должен быть одновременно PhysicalDevice и Сервер
Каждый VirtualServer должен быть одновременно VirtualDevice и Сервер
Каждое NetDevice представляет собой PhysicalDevice
Каждое StorageArray представляет собой PhysicalDevice

OneЯ полагаю, что решение состоит в том, чтобы дублировать код Server для PhysicalServers и VirtualServers , однако я чувствую, чтоs идет вразрез с тем, что я пытаюсь сделать, что наследуется.

Они должны быть отдельными классами, потому что каждый из типов будет иметь свойства и методы.Например, Сервер будет иметь OSCaption, Memory, Procs и т. Д. PhysicalDevice будет иметь такие вещи, как Location, Serial, Vendor и т. Д. И VirtualDevice будет иметь ParentDevice, State, VHDLocation и т. Д.

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

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

, что-то вроде ... PhysicalServer : IAsset : IServer : IPhysical

Я нахожусь в глубокой воде, поэтому на самом деле просто ищу советы или рекомендации.

Ответы [ 4 ]

8 голосов
/ 16 февраля 2012

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

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

Пример - Наследование + Композиция

public class PhysicalServer : Asset
{
    public PhysicalInfo PhysicalProperties
    {
         get;
         set;
    }
}

public class VirtualServer : Asset
{
    public VirtualInfo VirtualProperties
    {
         get;
         set;
    }
}

Пример - только состав

public class VirtualServer
{
    public VirtualInfo VirtualProperties
    {
         get;
         set;
    }

    public AssetInfo AssetProperties
    {
         get;
         set;
    }
}

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

Пример - Наследование + Композиция + Обобщенный член, который наследуется от общего типа

public class VirtualServer<TVirtualInfo> : Asset
   where TVirtualInfo : VirtualDeviceInfo
{
    public TVirtualInfo VirtualProperties
    {
         get;
         set;
    }
}

public class VirtualServerInfo : VirtualDeviceInfo
{
   // properties which are specific to virtual servers, not just devices
}

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

3 голосов
/ 16 февраля 2012

Используйте миксин.

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

public class PhysicalServer : Server

Затем вы добавляете интерфейсы для других функций.

public class PhysicalServer : Server,IAsset,IVirtualDevice

И вы добавляете методы расширения к интерфейсам.

public static int WordCount(this IAsset asset)
{
  //do something on the asset
}

Вот статья о миксинах, если мой ответ слишком прост: http://www.zorched.net/2008/01/03/implementing-mixins-with-c-extension-methods/

1 голос
/ 16 февраля 2012

C # не поддерживает множественное наследование от классов (но поддерживает множественные реализации интерфейсов).

То, что вы просите, это не множественное наследование. Множественное наследование - это когда один класс имеет более одного базового класса. В вашем примере каждый класс наследует от одного / нуля других классов. Актив и Сервер являются базовыми базовыми классами. Таким образом, у вас нет проблем с этим в c #, вы можете просто определить общие функции, например, server , а затем делать разные вещи в VirtualDevice и PhysicalDevice .

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

0 голосов
/ 16 февраля 2012

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

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

Вам нужно смотреть на это под углом того, что «меняется»в будущем, а не смотреть на иерархическую диаграмму классов.Диаграмма классов не может быть иерархической, вместо этого она должна представлять «что меняется», а что «остается постоянным».Из того, что я вижу, в будущем вы можете определить MobileDevice, VirtualMobileDevice.

В ваших текущих классах у вас, кажется, есть свойства, такие как Vendor, Serial.Они могут быть необходимы в MobileDevice тоже верно?Таким образом, вам нужно изменить свое мышление, чтобы на самом деле думать о поведении, а не о классах, которые имеют иерархический смысл.

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

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

Подумайте о «фабриках» (для создания), стратегии (для общей функциональности / обработки).

Отредактировано:

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

...