[Zope3-dev] Re: "most specific" interface?

Philipp von Weitershausen philipp at weitershausen.de
Tue Sep 13 04:23:31 EDT 2005


Jean-Marc Orliaguet wrote:
> is the order of the list of interfaces implemented by an object subject
> to internal changes?
> 
> I have identified the need for such a pattern:
> 
>     iface = object.interface()
> 
> with:
> 
> class someObject(object):
>     implements(IMainInterface, ISecondaryInterface, ...)
>     def interface():
>         """Return the most specific interface implemented by the element."""
>         return list(providedBy(self))[0]
> 
> to be able in that case to get access to the first interface implemented
> by an object, as a sort of main object type.

We usually do this differently. If some interfaces are special types
(e.g. IFile is a content type) then we have this interface provide
ISpecialType (e.g. IFile provides IContentType). ISpecialType is an
interface extending IInterface.

Then, no matter where in the list of provided interfaces the type is, it
can be fetch with queryType. Let's take the IFile example from above and
set it up as a content type:

  >>> from zope.app.content.interfaces import IContentType
  >>> from zope.app.file.interfaces import IFile
  >>> from zope.interface import directlyProvides
  >>> directlyProvides(IFile, IContentType)

Now let's make a File object. We see that its first interface isn't
IFile but IFileContent:

  >>> from zope.app.file.file import File
  >>> f = File()
  >>> list(providedBy(f))
  [<InterfaceClass zope.app.publication.interfaces.IFileContent>,
   <InterfaceClass zope.app.file.interfaces.IFile>,
   <InterfaceClass persistent.interfaces.IPersistent>]

Yet, when we query the content type, we get IFile as expected.

  >>> from zope.app.interface import queryType
  >>> queryType(f, IContentType)
  <InterfaceClass zope.app.file.interfaces.IFile>

> the zope/app/component/registration.txt documentation mentions:
> 
> """
> We can now write another `IComponentRegistration` implementation that knows
> about the interface; in fact, it will pick the most specific one of the
> component:
> 
>   >>> from zope.interface import providedBy
>   >>> class SomethingRegistration(Registration):
>   ...
>   ...     def interface(self):
>   ...         return list(providedBy(self._component))[0]
>   ...     interface = property(interface)
> 
> """
> 
> but I haven't seen it used anywhere else. Is it safe to use this?

I think it's not quite safe to rely on it the way you seem to want (as a
"main" object type). It is correct that the first interface *is* the
most specific one, e.g. when it comes to adaption:

  >>> from zope.component import *
  >>> from zope.interface import *

  >>> class IA(Interface): pass
  ...
  >>> class IB(Interface): pass
  ...
  >>> class IC(Interface): pass
  ...

  >>> class Adapter(object):
  ...     adapts(IA)
  ...     implements(IC)
  ...     def __init__(self, context): pass
  ...
  >>> class Bedapter(object):
  ...     adapts(IB)
  ...     implements(IC)
  ...     def __init__(self, context): pass
  ...

  >>> provideAdapter(Adapter)
  >>> provideAdapter(Bedapter)

  >>> class Klass(object):
  ...     implements(IA, IB)
  ...
  >>> IC(Klass())
  <__main__.Adapter object at 0x1424e30>

  >>> class Klass(object):
  ...     implements(IB, IA)
  ...
  >>> IC(Klass())
  <__main__.Bedapter object at 0x1424e10>

Philipp


More information about the Zope3-dev mailing list