2013-05-02 8 views
2

Учитывая следующий код:Проблемы с 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?

ответ

2

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

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>) 
+0

Есть ли способ использовать именованные абонентов? Я могу видеть, как их регистрировать, но не как их получить. – Ben

+0

@Ben: Именованные подписчики или именованные адаптеры? –

+0

@Ben: названные абоненты на самом деле являются функцией, которая еще не реализована (регистрация имени для абонента вызывает «TypeError» на данный момент). –