سؤال

Given the following code:

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

The output it produces is:

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

Why is an instance of AB returned? AB only declares that it adapts A and B. Is there a way I can achieve behavior where only AC would be returned?

هل كانت مفيدة؟

المحلول

You are listing subscribers. Subscribers are notified of all things that implement the interface(s) they are interested in.

C is a subclass of B, so the B subscriber is interested, and will be notified. The fact that C implements a little more is of no concern to the B subscriber, as the object will implement at least the B interface.

Subscribers are generic, they just want objects that implement their interface or subclasses thereof. Adapters are more specific:

>>> 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() enumerates all registered adapters, together with their names:

>>> 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>)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top