Это когда-либо действительно, чтобы преобразовать объект из базового класса в подкласс

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

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

Трудность возникает, когда сотрудник получает повышение до менеджера. Можно ли преобразовать базовый класс? Employee в наследственный класс Manager? Это неправильно. Я думаю, я бы сделал это с помощью специализированного конструктора Manager,

Помимо этого, NHibernate поддерживает такое поведение? это так просто, как получить сотрудника, создать менеджера из сотрудника, а затем сохранить менеджера?

6 ответов

Решение

Пока ваша бизнес-модель соответствует вашему домену, вы делаете правильные вещи.

Тем не менее, для меня это звучит так:

Manager Promote(Employee employee)
{
   var manager = new Manager();
   //promote your employee to a manager here
   return manager;
}

внутри какой-то рабочий процесс какой-то.

Что касается NHibernate, похоже, что вы смешиваете логику ORM со своей бизнес-областью. Повышение сотрудника до руководителя является структурой бизнес-домена и, как таковое, относится к вашей бизнес-модели. Однако то, как NHibernate отображает ваших сотрудников и ваших менеджеров в вашу БД, не имеет ничего общего с вашей бизнес-моделью, за исключением того, как их сопоставить. Это определенно не имеет ничего общего с тем, как повысить сотрудника до менеджера.

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

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

Лично у меня был бы базовый класс со всеми основными вещами и списком ролей.
Каждая роль имеет свои свойства и функциональность.
Преимущества в два раза:

  • Легко дать или взять на себя роль человеку
  • Это позволит вашим сотрудникам выполнять несколько ролей без необходимости проводить "комбинированные занятия".

Если вы идете с единичным наследованием, то переход с наследованием скоро предоставит вам такие классы, как "ManagerProgrammer", "ProgrammerStockManager", "ProgrammerSupport"

Да, это действительно. Что касается реализации, вы можете использовать:

  • Статический метод на менеджере: public static Manager Promote(Employee employee) { ... }
  • Специализированный конструктор на менеджера
  • Фабрика или класс обслуживания

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

Контакт является атрибутом Сотрудника. Работник (ваш сотрудник) - это роль, менеджер - это роль. Работник и менеджер все еще являются сотрудниками, но имеют роли. Роль - это отношения IN IN, сотрудник - это отношения AM A, а контакт - это отношения HAS A. У сотрудника есть контакт (1-1 отношения) Один контакт на сотрудника (1-M, если у него два телефона и т. Д., Но я отвлекся) Сотрудник ВХОДИТ в роль (отношения ММ) Многие сотрудники много ролей Сотрудник А (отношение M-1) - Многие сотрудники, все из сотрудников типа.

Итак, вы меняете роли.

G'day,

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

Мне кажется, что вы неправильно представляете объект Manager.

Вернитесь к основам и подумайте в терминах ОО, где ваш базовый класс (контакт) содержит общие элементы объектов Employee и Manager. Любые производные объекты являются просто специализациями базового класса.

В этом случае менеджер не является экземпляром сотрудника?

Классы Manager и Employee должны иметь элемент данных reportsTo, который также имеет тип Employee.

Единственное отличие, которое я вижу на данный момент, состоит в том, что объект Manager теперь имеет коллекцию объектов Employee, которые являются их собственными directReports. Вероятно, это должно быть реализовано в виде указателя на контейнер объектов Employee.

Я не могу представить какую-либо специализацию в поведении, которая должна отделять объект Employee от объекта Manager.

Хм, может быть, сделать базовый класс Person, который содержит контактные данные в нем.

Изменить: Извините, из вашего комментария, я думаю, я не был достаточно ясен. То, что я описал, не приводит к двум отдельным классам, которые оба напрямую связаны с вашим классом Contact, так что вы должны изменить экземпляр Employee на Manager во время выполнения, что было вашим первоначальным вопросом.

То есть я не думаю, что у вас должно быть два производных класса, Employee и Manager, которые наследуются напрямую от вашего класса Contact.

Разве оба эти типа людей не работают в компании? Почему следует различать менеджера и сотрудника? Сотрудник больше не Сотрудник, если он становится Менеджером?

ИМХО совершенно неправильно иметь два производных класса, менеджера и сотрудника. Вы пытались сломать вещи с точки зрения "Иса" и "имеет" отношения. Тогда вы можете увидеть, что ваша базовая структура неверна.

Сказать, что сотрудник "isa" контакт просто не имеет смысла. Скорее всего, Сотрудник "isa" Персона и Персона "имеет" набор Контактных данных.

Может быть, вывести класс менеджера как специализацию сотрудника? Сотрудник "isa" Персона. Менеджер "isa" Сотрудник, который "isa" Персона.

НТН

веселит,

Другие вопросы по тегам