2013-05-02 51 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

您正在查看的商品訂戶。用戶被告知所有實現他們感興趣的接口的東西。

CB的子類,所以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 2013-05-02 16:18:19

+0

@Ben:指定的訂戶或指定的適配器? – 2013-05-02 16:18:55

+0

@Ben:指定的訂閱者實際上是一個尚未實現的功能(註冊一個用戶名稱此時引發了一個「TypeError」)。 – 2013-05-02 16:21:22