Это когда-либо действительно, чтобы преобразовать объект из базового класса в подкласс
В моем приложении в настоящий момент (как и во многих других приложениях) сущность называется 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" Персона.
НТН
веселит,