Проблема с абонентскими адаптерами zope.component, адаптирующими несколько объектов

Учитывая следующий код:

from zope.component import getGlobalSiteManager, adapts, subscribers
from zope.interface import Interface, implements


class A(object): pass
class B(object): pass
class C(B): pass

class AB(object):
    implements(Interface)
    adapts(A, B)

    def __init__(self, a, b):
        pass

class AC(object):
    implements(Interface)
    adapts(A, C)

    def __init__(self, a, c):
        pass

gsm = getGlobalSiteManager()
gsm.registerSubscriptionAdapter(AB)
gsm.registerSubscriptionAdapter(AC)

a = A()
c = C()

for adapter in subscribers([a, c], Interface):
    print adapter

Выходные данные:

<__main__.AB object at 0xb242290>
<__main__.AC object at 0xb2422d0>

Почему возвращается экземпляр AB? AB только заявляет, что он адаптирует A и B. Есть ли способ, которым я могу добиться поведения, при котором будет возвращен только AC?

1 ответ

Решение

Вы перечисляете подписчиков. Подписчики уведомляются обо всех вещах, которые реализуют интересующий их интерфейс.

C это подкласс B, Итак B подписчик заинтересован и получит уведомление. Дело в том, что C реализует немного больше не имеет никакого отношения к B подписчик, так как объект будет реализовывать как минимум B интерфейс.

Подписчики являются общими, они просто хотят объекты, которые реализуют их интерфейс или их подклассы. Адаптеры являются более конкретными:

>>> gsm.registerAdapter(AB)
>>> gsm.registerAdapter(AC)
>>> from zope.component import getAdapters
>>> for adapter in getAdapters((a, c), Interface):
...     print adapter
... 
(u'', <__main__.AC object at 0x104b25a90>)

getAdapters() перечисляет все зарегистрированные адаптеры вместе с их именами:

>>> class AnotherAC(object):
...     implements(Interface)
...     adapts(A, C)
...     def __init__(self, a, c): pass
... 
>>> gsm.registerAdapter(AnotherAC, name=u'another')
>>> for adapter in getAdapters((a, c), Interface):
...     print adapter
... 
(u'', <__main__.AC object at 0x104b25ed0>)
(u'another', <__main__.AnotherAC object at 0x104b25a90>)
Другие вопросы по тегам