インターフェース

はじめに

インターフェースはオブジェクトによって提供されるメソッドを定義しています。 Plone は異なったサブシステムとの間の API 定義するためにインターフェースを広範囲で使用しています。 これはダックタイピングが十分ではないときに、二つの異なったオブジェクト間のブリッジを定義するよりも、一貫して宣言された方法を提供します。

インターフェースは異なった形の断片をはめ込めるように穴の形を定義するようなものです。 断片の形はインターフェースによって定義されますが、色や材質その他の詳細は実装により変更することが可能です。

zope.interface package README を参照してください。

1つ以上のインタフェースを実装する

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)

オブジェクトが提供するインターフェースを確認する

providedBy メソッド

Python では以下のコードを使用して確認できます。:

from yourpackage.interfaces import IMyInterface

if IMyInterface.providedBy(object):
        # 実装を行ないます
else:
        # 必要としたオブジェクトではありません

plone_interface_info ヘルパービュー

ページテンプレートでは 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を取得する

インターフェース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

文字列idからインターフェースのクラスを取得する

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

複数のコンテントタイプにインターフェースを適用する

古い形式のコンテントタイプに対してインターフェースをあとで追加することができます。

以下のようなユースケースが考えられます。

  • 特別なコンテントタイプに対して viewlet を割り当てたい。
  • 特定のコンテントタイプに対して特定の動作を有効にしたい。

ノート

いくつかの別な関連付けられていないクラスに対して共通の呼び出し方を作成したい場合にだけ改造する必要があります。 明示的にインターフェースのマーカーを作成することなく、コンテクストとして一つの既存のクラスまたはインターフェースを使用できます。 通常 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.dottedname は allows you to resolve dotted names to Python objects manually

動的インターフェース

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

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.