Хорошо, я объясню это.
Традиционное наследование в Python не расширяет базовый класс. Итак, если вы расширите A
от B
, тогда A
будет объектом типа A
и B
. Если вы создаете объект типа B
. Не будет ничего от A
. Было бы смешно иметь что-то вроде этого:
SortedDict(dict)
RandomDict(dict)
....
И тогда dict стал _9 _, _ 10 _...
Для python, поскольку вы расширяете то, что хотите, вам необходимо импортировать конкретный класс, из которого вы хотите расширить, и при необходимости использовать этот конкретный новый класс. На практике в Python мы не расширяем много классов, поскольку в большинстве случаев в этом нет необходимости.
Теперь об одоо.
- Odoo _inherit
Odoo состоит из модулей очень много модулей. Если нам нужно знать каждую модель, которая была унаследована для расширения конкретной модели. Нам пришлось бы изменить представления, чтобы они ссылались на последнюю расширенную модель ... Было бы сложно указать, какой класс использовать.
Решение простое: сделайте всю модель наследником ModelClass. Внутри определения класса сохраните инструкцию, которая сообщает odoo, какую модель базы данных следует расширить. Мы можем ссылаться в наших представлениях на одну единственную модель, и odoo позаботится о наследовании модели (а не о наследовании классов) во время выполнения. Это позволит нам использовать super
в методах для вызова методов, определенных в определениях родительской модели ... Приятно то, что нам не нужно знать BaseClass, в котором расположен метод. В противном случае нам нужно было бы знать конкретный класс, у которого есть модель, но поскольку модули могут быть добавлены / удалены, невозможно узнать, какой класс является последним в цепочке наследования модели. Вот почему _inherit
в значительной степени необходим. Мы создаем подклассы не классов, а моделей. Это не совсем питонический, но если бы мы хотели сделать его питоническим, нам пришлось бы неявно расширить модель с помощью синтаксического сахара (который также не совсем питонический) ... Так что технически явное определение того, какую модель мы хотим расширить, является более питоническим чем при использовании стандартной схемы наследования классов. Если подумать, в этом есть смысл.
- Почему используется расширение
Я в значительной степени это объяснил. Но вы должны понимать, что множество модулей можно загружать в неопределенном порядке. Вот почему расширение имеет смысл. Методы могут вызываться в разном порядке, но все равно все должно работать правильно. Если у вас загружено несколько модулей, ваш код все равно должен работать, когда модуль, о котором вы никогда не знали, будет добавлен в odoo. Способ работы наследования не является полностью недетерминированным, но в некоторых случаях порядок загрузки может отличаться на некоторых компьютерах / серверах.
- _inherits имеет большой смысл.
Это самое близкое к традиционному наследованию классов Python для моделей.
Когда вы используете _inherits, дочерняя модель не расширяет базовую модель, от которой вы наследуете. Он используется для создания новой модели, которая не дублирует атрибуты родительской модели. Помните, мы создаем объекты базы данных. Сохраняется ссылка на родительский объект, содержащий дополнительные атрибуты. Один простой пример - это res.partner и res.user. Вкратце, res.user - это res.partner с логином и паролем ... Не имеет смысла добавлять логин / пароль ко всем res.partners, которые не являются пользователями ... И это вроде здорово чтобы иметь возможность повторно использовать весь пользовательский интерфейс res.partner для пользователей res.users. Если бы у odoo не было наследования, нам пришлось бы полностью дублировать пользовательский интерфейс / db res.partner для res.users ... и мы не могли бы легко использовать res.users там, где должен быть res.partner использовано .... Простое решение - сохранить идентификаторы разных моделей и сохранить ссылку ... Но было бы здорово иметь доступ к "user.name" вместо "user.partner_id.name". Очевидно ... В Python вы не пишете ... "obj.super.property", чтобы получить доступ к свойствам родительского класса? Технически здесь то же самое. поля делегируются ...
Теперь почему методы не делегируются? Я предполагаю, что это в значительной степени связано с проблемой с делегатами в множественном наследовании. Если вы _унаследуете несколько моделей, которые имеют приоритет над write
или _14 _... К какой из них вы будете звонить? Технически ни один из методов не должен вызываться, потому что они определены в родительском объекте. Поэтому, если вы хотите вызвать метод res.partner для объекта res.users
, self
, который будет отправлен родительскому методу, будет res.user
, а не _18 _... Что вызовет проблемы, поскольку res.partner
не ожидает, что он будет называется res.users
. Даже если вы вызовете метод "res.partner" со ссылкой partner_id
... Тогда откуда, черт возьми, вы знаете, что значения, переданные в res.users
, действительно должны быть переданы res.partner
? По этой причине безопаснее явно вызывать нужные методы с partner_id.write
с явными значениями, которые вы хотите отправить. Для атрибутов не очень важно знать, какой атрибут будет использоваться. Теоретически это довольно детерминировано. Я не пробовал, но есть вероятность, что запись для атрибута будет делегирована конкретному родителю в зависимости от порядка, в котором создаются поля делегата. Dict, в котором хранится запись _inherits
, будет возвращать значения в определенном порядке. И поскольку вы все время будете читать / писать из одного и того же объекта, в большинстве случаев не имеет значения, какой родитель будет владеть данными, если существуют повторяющиеся атрибуты. Также есть возможность добавить больше делегированных полей или указать конкретное поле для делегирования, так что технически здесь нет проблем. Но для методов, как я объяснил, вы не можете ожидать, что odoo будет знать, какой метод следует делегировать, а какой нет, поэтому лучше перестраховаться и явно попросить программиста сказать, что делать.
person
Loïc Faure-Lacroix
schedule
27.03.2017