Рассмотрим следующий пример:Python: переименование методов суперкласса и их функции-Scope ссылки
class Company():
def hireEmployee():
def fireEmployee():
def promoteEmployee():
etc...
class EngineeringFirm(Company):
pass
class PaintingFirm(Company):
pass
Пусть класс Компания имеет намного больше методов. Что делать, если я хочу переименовать эти методы из суперкласса, чтобы получить следующее:
class EngineeringFirm(Company):
def hireEngineer():
...
class PaintingFirm(Company):
def hirePainter():
...
... и так далее. Хотя использование «Employee» в этом сценарии действительно не повредило бы, это действительно просто иллюстрирует идею. Как я могу это сделать?
Моя идея состояла в использовании функции classFactory, которая использовала бы тип сотрудника как аргумент и генерировала бы класс компании, в то время как метаклас обрабатывал бы переименование путем итерации через словарь атрибутов и замены «Employee» указанным типом.
class EngineeringFirm(companyFactory('Engineer'))
...
Единственная проблема заключается в следующем: что, если методы внутри Компании совершают вызовы друг к другу по умолчанию «Employee»? Вот где я в тупике. У меня возникла идея, что метакласс, участвующий в переименовании методов, также может получить источник каждой функции (через модуль проверки) и выполнить поиск, если обнаружен известный атрибут метода внутри и, если это так, заменить эту часть и создать новую функцию через exec и присвоить его правильному ключу атрибута.
... Но это действительно похоже на хакерство. Я открыт для альтернатив, и хотя я понимаю, что могут возникнуть проблемы с дизайном с вопросом (я также открыт для предложений на этом фронте). Мне было бы интересно узнать, имеет ли эта проблема более элегантное решение.
Спасибо!
Edit: другое решение
Ради аргумента, я на минуту предположим, что приведенный выше код действительно то, что я работаю с; Я подумал, что могу затронуть некоторые проблемы в комментариях другим решением, которое я имел в виду, которое я уже рассмотрел и убрал по причинам, которые я объясню.
Если Firm
классы, унаследованные от компании, и я хотел, чтобы поддерживать идентичный интерфейс (как один обычно будет в таком случае, как это разрешить динамические вызовы hire()
или promote()
, и т.д.) я мог бы реализовать __getattribute__
, который принимает HirePainter()
(по доступ к исходному методу Employee), в то же время позволяя любому другому интерфейсу использовать HireEmployee()
, если это необходимо.
Интересно, полагая, что это нормально, чтобы продлить мой вопрос, если это то, что считается плохим, если, скажем, я планировал сделать это, потому что я думал, что код внутри PaintingFirm
принесет пользу в читабельности? Опять же, я понимаю, что этот пример ужасен в том, что читаемость здесь действительно не приносит никакой пользы, но предположим, что это так?
(Единственная причина, по которой я не предлагал эту идею, в первую очередь состоит в том, что мой __getattribute__
уже обрабатывает совсем немного, и добавление дополнительного шума к ней не было таким привлекательным. Тем не менее, я мог бы работать, но это вопрос, который я должен был задать, если бы там были более волшебные (но не взломанные) решения ..)
[EEEEEEEEEWWWWWWWWWWWWW] (http://en.wikipedia.org/wiki/Liskov_substitution_principle) –
@ Eithos Ну, дело в том, что ваши фирмы должны иметь похожий, если не идентичный интерфейс, чтобы вы могли указать любой твердый объект нанять кого-то, и позволить ему решать, кого он нанимает. Таким образом, вы можете сделать 'firm.hire()', не зная, что именно «фирма». – glglgl
@glglgl Интересно. Это заставляет меня чувствовать себя глупо, потому что в большинстве других ситуаций это, вероятно, так, как я бы справился с этим. Делает совершенный смысл. Я понимаю, что проблема осложняется тем фактом, что я действительно не разместил свой настоящий код, и есть очень мало шансов, что любой другой класс должен/должен иметь доступ к 'firm.hire()'. Другими словами, при использовании 'firm.hire' будет способствовать динамичным вызовам на прокат, не зная заранее фирму, эта динамическая обработка действительно не понадобится. Фактически, эти вызовы активируются с помощью событий пользовательского интерфейса, которые ... – Eithos