インターフェースはオブジェクトによって提供されるメソッドを定義しています。 Plone は異なったサブシステムとの間の API 定義するためにインターフェースを広範囲で使用しています。 これはダックタイピングが十分ではないときに、二つの異なったオブジェクト間のブリッジを定義するよりも、一貫して宣言された方法を提供します。
インターフェースは異なった形の断片をはめ込めるように穴の形を定義するようなものです。 断片の形はインターフェースによって定義されますが、色や材質その他の詳細は実装により変更することが可能です。
zope.interface package README を参照してください。
zope.interface.implements() をクラスのボディ部分で使用します。 複数のインターフェースは引数のリストによって指定できます。
例:
from zope.interface import implements
from collective.mountpoint.interfaces import ILocalSyncedContent
from ora.objects.interfaces import IORAResearcher
class MyContent(folder.ATFolder):
"""A Researcher synchronized from ORA"""
implements(IORAResearcher, ILocalSyncedContent)
Python では以下のコードを使用して確認できます。:
from yourpackage.interfaces import IMyInterface
if IMyInterface.providedBy(object):
# 実装を行ないます
else:
# 必要としたオブジェクトではありません
ページテンプレートでは plone_interface_info ヘルパービューを使用します。:
<div tal:define="iinfo context/@@plone_interface_info">
<span tal:condition="python:iinfo.provides('your.dotted.interface.IName')">
実装を行ないます
</span>
</div>
以下を参照して下さい。
インターフェースの解決の順番(IRO: Interface Resolution Order)はオブジェクトが提供する(直接またはクラスによって実装された)インターフェースのリストです。
インターフェースのリストは0番目(優先度が高い)から最後(優先度低い)まで順番に評されます。
オブジェクトのデバッグをするときに以下のような不思議な属性を指定すると、この情報にアクセスできます。:
object.__provides__.__iro__.
ノート
アダプターファクトリーは動的な(アダプターインターフェースはオブジェクトにハードコードされていない)ため、オブジェクトは __iro__ のリストに入っていないインターフェースに適応することができます。
インターフェースidは __identifier__ 属性に保存されています。
yourpackage/interfaces.py というファイルの例です。:
import zope.interface
class IFoo(zope.interface.Interface).
pass
# id は yourpackage.interfaces.IFoo になります
id = IFoo.__identifier__
この属性は import 時の別名には対応していません。
例:
Products.ATContentTypes.interfaces.IATDocument.__identifier__ is
Products.ATContentTypes.interfaces.document.IATDocument
zope.dottedname パッケージ を使用します。
例:
import zope.interface
from zope.dottedname.resolve import resolve
class IFoo(zope.interface.Interface).
pass
# id は yourpackage.interfaces.IFoo です
id = IFoo.__identifier__
interface_class == resolve(id)
assert IFoo == interface_class
古い形式のコンテントタイプに対してインターフェースをあとで追加することができます。
以下のようなユースケースが考えられます。
ノート
いくつかの別な関連付けられていないクラスに対して共通の呼び出し方を作成したい場合にだけ改造する必要があります。 明示的にインターフェースのマーカーを作成することなく、コンテクストとして一つの既存のクラスまたはインターフェースを使用できます。 通常 zope.interface.Interface をコンテクストとして承認している場所では、通常の Python クラスも同様に扱うことが(insinstance の振るまいにより)可能です。
ZCML の <class> 宣言を使用して、いくつかのクラスにインターフェースを割り当てることができます。:
<!-- List of content types where last modified viewlet is enabled -->
<class class="Products.ATContentTypes.content.document.ATDocument">
<implements interface=".interfaces.ILastModifiedSupport" />
</class>
<class class="Products.ATContentTypes.content.event.ATEvent">
<implements interface=".interfaces.ILastModifiedSupport" />
</class>
<class class="Products.ATContentTypes.content.newsitem.ATNewsItem">
<implements interface=".interfaces.ILastModifiedSupport" />
</class>
そしてこれらのコンテントタイプでは以下のように使用するために viewlet を持つことができます(grok を使用した例)。:
from five import grok
from interfaces import ILastModifiedSupport
from plone.app.layout.viewlets.interfaces import IBelowContent
class LastModified(grok.Viewlet):
""" Viewlet to show the document last modification time.
This is enabled on Page, Event and News Item wich implement ILastModofiedSupport marker interface.
"""
grok.context(ILastModifiedSupport)
grok.viewletmanager(IBelowContent)
関連文書
Zope はコンテンツのオブジェクトに対して ZMI で動的にインターフェースを有効または無効にすることができます。 各オブジェクトの Interfaces タブを選択して実行します。
インターフェースのマーカーを Zope が見つけられるようにするために、 ZCML の <interface> ディレクティブを使用して明示的に宣言する必要があります。:
<!-- Declare marker interface, so that it is available in ZMI -->
<interface interface="mfabrik.app.interfaces.promotion.IPromotionsPage" />
ノート
インターフェースのドット付きの名前は直接インターフェースクラスを指定しなければなりません。 また __init__.py のような他のモジュール経由では import できません。
Products.Five の mark() 関数を使用します。
例:
from Products.Five.utilities.marker import mark
mark(portal.doc, interfaces.IBuyableMarker)
Tagged values are arbitary metadata you can stick on zope.interface.Interface subclasses. For example, plone.autoform <http://pypi.python.org/pypi/plone.autoform>`_ package uses them to set form widget hints for ``zope.schema data model declarations.