Скажем, то, что я имею class
, это использует некоторую функциональность dict
. Я раньше составлял a dict
возразите внутри и обеспечьте некоторый доступ с внешней стороны, но недавно думал о простом наследовании dict
и добавление некоторых атрибутов и методов, которых я мог бы потребовать. Действительно ли это - хороший способ пойти, или я должен придерживаться состава?
Очень часто злоупотребляют наследованием. Если ваш класс не предназначен для использования в качестве универсального словаря с дополнительной функциональностью, я бы сказал, что композиция - это лучший способ.
Сохранение переадресации вызовов обычно не является достаточной причиной для выбора наследования.
Из книги «Шаблоны проектирования»:
Отдайте предпочтение композиции объектов над наследованием классов
В идеале вам не нужно создавать новых компонентов для повторного использования. Вы должны иметь возможность получить все функции, которые вам нужны, путем сборки существующих компонентов с помощью композиции объекта . Но это редко бывает , потому что на практике набор доступных компонентов никогда не бывает достаточно богатым . Повторное использование путем наследования упрощает создание новых компонентов , которые могут быть составлены из старых. Таким образом, наследование и композиция объектов работают вместе.
Тем не менее, по нашему опыту, дизайнеры злоупотребляют наследованием как техникой повторного использования, и проекты часто делаются более пригодными для повторного использования (и проще) в зависимости от большего по составу объекта »
Полный текст здесь: http://blog.platinumsolutions.com/node/129
Должен isinstance (my_object, dict)
возвращать True или False? Другими словами, если вы случайно передадите один из объектов чему-то, кому нужен диктат
, должен ли он беспечно попытаться использовать его как дикт
? Наверное, нет, поэтому используйте композицию.
Оба варианта хороши, но я бы предпочел наследование, поскольку это означает меньше кода (что всегда хорошо, пока он читабелен).
В Dive into Python есть очень подходящий пример.
В Python 2.2 и предыдущих версиях вы не могли создавать подклассы из встроенных элементов напрямую, поэтому вам приходилось использовать композицию.
class FileInfo(dict): "хранить метаданные файла" def __init__(self, filename=None): self["name"] = filename
- Первое отличие заключается в том, что вам не нужно импортировать модуль UserDict, поскольку dict является встроенным типом данных и всегда доступен. Второе заключается в том, что вы наследуете от dict напрямую, а не от UserDict.UserDict.
- Третье различие тонкое, но важное. Из-за того, как работает UserDict внутри, он требует, чтобы вы вручную вызывали его
__init__
метод, чтобы правильно инициализировать его внутренние структуры данных.dict
работает иначе; это не обертка, и она не требует явной инициализации.
. Вам действительно нужно взвесить стоимость и объем того, что вы пытаетесь сделать. Наследование от dict
, потому что вы хотите, чтобы поведение, подобное словарю, было быстрым и простым, но подвержено ограничениям, таким как создание нехэшируемых объектов, созданных из вашего класса.
Так, например, если вам нужно сериализовать (например, pickle
) объекты, но при этом требуется поведение, подобное словарю, то, очевидно, вы не можете наследовать напрямую от dict
, и вам нужно будет скомпоновать части функциональности, которые вы хотите, чтобы это произошло.