питон: наследование или композиция - PullRequest
15 голосов
/ 05 марта 2010

Допустим, у меня есть class, который использует некоторые функции dict. Раньше я компоновал объект dict внутри и предоставлял некоторый доступ извне, но недавно думал о простом наследовании dict и добавлении некоторых атрибутов и методов, которые мне могут понадобиться. Это хороший путь или я должен придерживаться композиции?

Ответы [ 4 ]

13 голосов
/ 05 марта 2010

Наследование очень часто злоупотребляют. Если ваш класс не предназначен для использования в качестве общего словаря с дополнительной функциональностью, я бы сказал, что состав - это путь.

Сохранение переадресации вызовов обычно не является достаточной причиной для выбора наследования.

Из книги образцов дизайна:

Пользуется композицией объектов по наследованию классов

В идеале вам не нужно создавать новые компоненты для достижения повторного использования. Вы должен быть в состоянии получить все функциональность вам нужна путем сборки существующие компоненты через объект состав. Но это редко случай, потому что набор доступных компоненты никогда не бывает достаточно богатым на практике. Повторное использование по наследству облегчает производство новых компонентов это может быть составлено со старыми. Наследование и состав объекта Таким образом, работать вместе.

Тем не менее, наш опыт таков, что дизайнеры злоупотребляют наследованием как повторное использование техники и дизайна часто сделал более многократно (и проще) зависит больше от состава объекта. "

Весь текст здесь: http://blog.platinumsolutions.com/node/129

3 голосов
/ 06 марта 2010

Должен ли isinstance(my_object, dict) возвращать True или False?Другими словами, если вы случайно отдаете один из объектов чему-то, что хочет dict, должен ли он беспечно попытаться использовать его как dict?Наверное, нет, поэтому используйте композицию.

3 голосов
/ 06 марта 2010

Вы действительно должны взвесить стоимость и объем того, что вы пытаетесь сделать. Наследование от dict, потому что вы хотите, чтобы поведение, подобное словарю, было быстрым и легким, но подвержено ограничениям, таким как создание объектов, созданных из вашего класса, не подлежащими обработке.

Так, например, если вам нужно сериализовать (то есть pickle) объекты, но также нужно поведение, подобное словарю, то, очевидно, вы не можете наследовать напрямую от dict, и вам необходимо составьте части функций, которые вы хотите, чтобы это произошло.

3 голосов
/ 05 марта 2010

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

У погружения в Python есть очень актуальный пример .

В Python 2.2 и более ранних версиях вы не могли напрямую создавать подклассы из встроенных модулей, поэтому у было для использования композиции.

class FileInfo(dict):                  
   "store file metadata"
   def __init__(self, filename=None): 
       self["name"] = filename
  1. Первое отличие заключается в том, что вам не нужно импортировать модуль UserDict, поскольку dict является встроенным типом данных и всегда доступен. Во-вторых, вы наследуетесь непосредственно от dict, а не от UserDict.UserDict.
  2. Третье отличие тонкое, но важное. Из-за того, что UserDict работает внутри, он требует, чтобы вы вручную вызвали его метод __init__ для правильной инициализации его внутренних структур данных . dict не работает так; это не оболочка, и не требует явной инициализации .
...