Я столкнулся с головоломкой. Я думаю, что должен знать, как это решить - я очень осведомлен и опыт в Python, но я не могу понять это. Кажется, что то, с чем я борюсь, должно быть обращено с помощью шаблона дизайна, который является вариацией на заводскую тему, но я не могу его вспомнить. (В конце этой записи я предлагаю техническое решение, но это кажется неправдоподобным). Надеюсь, вы сочтете эту дискуссию интересной сама по себе, но я с нетерпением жду некоторых предложений по решению моей проблемы.Как ограничить создание объектов одного класса экземплярами другого в Python?
Данные классы, A, B, C и D, я хочу ограничить создание экземпляров B методами экземпляров A, C методам B и D экземпляров методам C - другими словами, экземпляры фабрики для экземпляров B, B - экземпляры для экземпляров C, а C - фабрики для экземпляров D. (Я также хочу, чтобы каждый экземпляр D сохранял экземпляр C, созданный им, каждый экземпляр C, чтобы сохранить экземпляр B, созданный им, и каждый экземпляр B для хранения экземпляра A, созданного им, но это легко выполняется каждый экземпляр представляет себя как аргумент __init__
, когда он создает экземпляр следующего класса вниз в иерархии.)
Это классы модельного уровня, которыми управляет приложение. Нет никаких проблем с приложением, управляющим экземплярами B, C или D, просто не следует создавать их напрямую - все, что должно быть в состоянии создать напрямую, - это экземпляры A (и A может быть даже одиночным). Существуют различные виды проверки, управления, отслеживания, аудита и т. Д., Которые могут быть реализованы в методах одного класса, которые создают экземпляры следующего.
Примером может быть операционная система, которая может создавать файловые системы, которые могут создавать каталоги, которые могут создавать файлы, но код приложения должен следовать этой цепочке. Например, даже если у него были руки на Каталоге, он не должен был бы создавать файл, дающий File.__init__
экземпляр Каталога, даже если это то, что будут делать каталоги при запросе создания файла.
Я ищу дизайнерское решение, подкрепленное некоторой реализацией, а не что-то защищенное пользователем - я понимаю, что тщетность последнего.
Единственное, что я думал так далеко:
- начать все имя класса, за исключением А с подчеркиванием
- _b доступа() только из случаев, _C() только из экземпляров B, и _D() только из экземпляров _c
- полагаются на прикладном уровне программистов соблюдать эту договоренность и непосредственно создавать экземпляры только (возможно одиночки) класса а
Модуль уровня «прятался» по исключение класса из списка __all__
модуля недостаточное, поскольку только влияет на конструкции import *
- другой модуль все еще может достичь класса на import module
, затем ссылаясь на module.class
.
(Все это смутно напоминает проблемы C++, для которых требуется, чтобы два класса были друзьями, потому что они участвуют в двухсторонних отношениях: экземпляры каждого класса должны иметь возможность ссылаться на методы другого класса, которые управляют тем, что другая сторона отношения.)
Решение, которое может наилучшим образом соответствовать семантике и прагматике Python, заключается в определении D внутри C, C, определенных внутри B, и B, определенных внутри A. Это кажется ужасно уродливым способом втискивать несколько модулей стоимостью кода в один очень большой класс. (И представьте, если цепь опустилась еще на несколько уровней.) Это расширение более распространенных применений вложенных классов и, возможно, единственно технически обоснованного способа сделать это, но я никогда не видел такого рода структуру класса «русская кукла».
Идеи?
Было бы полезно, если бы вы могли бы сформулировать проблему лаконично в одном предложении, что вы отдельно от вашей собственной линии мысли и примеры. – noumenal
Это ужасно, но вместо того, чтобы пытаться сделать конструктор класса недоступным, вы можете проверить класс вызывающего метода во время построения, используя технику, аналогичную описанной здесь [http://stackoverflow.com/a/9812105/3895264]. Заметьте, я бы рекомендовал это, однако! – FujiApple
Разделение - хорошая идея - извините, я не думал об этом. –