Plone用接口来描述功能
Plone用接口来描述功能
http://www.315ok.org/blogfolder/100
http://www.315ok.org/logo.png
Plone用接口来描述功能
Plone用接口来描述功能
至此,我们已经描述来Zope2编程的核心概念。本章开始我们将着重介绍Zope3的新概念: interfaces,utilities, adapters, views, 和 events。
Interfaces 是Zope 3技术最关键的部分。 接口可以被认为是可以验证的文档——部件及他们的行为的描述,并能在运行时被检查。接口最简单的形式是标记接口——该接口仅仅描述一个部件的类型,而不必承诺任何方法和属性。由于Python语言没有一个专门为Interface 的构造器,所以我们定义接口用class,该class继承自zope.interface.Interface:
属性可以用zope.interface.Attribute来描述。对于属性的验证我们可以借助zope.schema来构造更精准的语句。详细情况我们将在11章自动生成表单中说明。当将对象的属性模块化时,在Zope3样式的代码中,优先采用attributes and Python properties 来代替分离的get 和set方法。
Here, we describe mechanisms for creating messages as communication factories.Because we are applying the interface to the class object, there is no notion of inheritance between the StrongMessage and the StandardMessage declarations—we have to declare the interface on both classes explicitly.
[size=5]Using Interfaces in Catalog Searches[/size]
In the previous section, we demonstrated how to use the catalog to search for objects by their portal_type, a string. This pattern is quite common, but has a few drawbacks:
Interfaces 是Zope 3技术最关键的部分。 接口可以被认为是可以验证的文档——部件及他们的行为的描述,并能在运行时被检查。接口最简单的形式是标记接口——该接口仅仅描述一个部件的类型,而不必承诺任何方法和属性。由于Python语言没有一个专门为Interface 的构造器,所以我们定义接口用class,该class继承自zope.interface.Interface:
>>> from zope.interface import Interface >>> class IBelievable(Interface): ... """An item which can be believed ... """通常,查阅一个包的接口是最快/最好的理解该包的所有部件是怎样组织在一起的。按照惯例,接口定义通常放在一个叫interfaces的模块中,所有接口名称开始是字母I,接口定义当中应该总要有一个有意义的文档字符串。通过运用接口程序设计可以模块化,可以实现继承和联合。例如,这是IBelievable接口的更具体化:
>>> class IUndeniable(IBelievable): ... """Something that is so believable it cannot be denied ... """接口也能描述方法和属性。注意方法在接口定义当中没有self参数,也不需要方法的body部分,尽管可以有文档字符串来表明方法的作用。当然,接口被一个class实现时,这个class将应有self参数,也有方法的body代码,请看下述例子。
属性可以用zope.interface.Attribute来描述。对于属性的验证我们可以借助zope.schema来构造更精准的语句。详细情况我们将在11章自动生成表单中说明。当将对象的属性模块化时,在Zope3样式的代码中,优先采用attributes and Python properties 来代替分离的get 和set方法。
Note that if you are using Python property syntax, you will not have an acquisition context. Since property getters and setters tend to be simple,this is not usually a problem, but if you find yourself needing one, look at Zope 2's ComputedAttribute class.
>>> from zope.interface import Attribute
>>> class IMessage(Interface):
... """A message being communicated
... """
...
... def shout(noise_level=5):
... """Shout the message
... """
...
... content = Attribute("The actual text of the message")
接口典型由classes来实现,这些classes的对象然后提供这些接口,这意味这每个对象都有该接口定义的方法和属性。>>> from zope.interface import implements >>> class StandardMessage(object): ... implements(IMessage) ... ... def __init__(self, content): ... self.content = content ... ... def shout(self, noise_level=5): ... print self.content * noise_level >>> class StrongMessage(StandardMessage): ... implements(IBelievable)接口继承自基类,一个类通过传输几个参数到implements()来实现多个接口。这个zope.interface 包含些方法来操作这些类和对象的接口。接口他们自己包含的方法能由于验证他们和类及对象的相互关系。
>>> IMessage.implementedBy(StandardMessage) True >>> IMessage.implementedBy(StrongMessage) True >>> IBelievable.implementedBy(StandardMessage) False >>> IBelievable.implementedBy(StrongMessage) True这里这个 implementedBy() 方法用于决定是否一个特定类的对象实现了给定的接口。过多时候我们用providedBy() 方法直接检查对象:
>>> fender = StandardMessage("All Fender guitars rock")
>>> strats = StrongMessage("Stratocasters are great!")
>>> telecaster = StrongMessage("Telecasters are awesome!")
>>> IMessage.providedBy(fender)
True
>>> IMessage.providedBy(strats)
True
>>> IBelievable.providedBy(fender)
False
>>> IBelievable.providedBy(strats)
True
我们也可以直接应用接口到对象。下面这个 IUndeniable接口被直接应用到一个对象:>>> from zope.interface import alsoProvides >>> alsoProvides(telecaster, IUndeniable) >>> IUndeniable.providedBy(fender) False >>> IUndeniable.providedBy(telecaster) TrueIt is also possible to let a class object provide (as opposed to implement) an interface,in which case we are making a statement about the type of the class, rather than the type of objects of that class. We can even apply interfaces to other interfaces to group them logically, or apply interfaces to modules, to describe their public functions and variables. In normal programming, these constructs are rarely needed, but you may come across them in framework code.
Here, we describe mechanisms for creating messages as communication factories.Because we are applying the interface to the class object, there is no notion of inheritance between the StrongMessage and the StandardMessage declarations—we have to declare the interface on both classes explicitly.
>>> class ICommunicationFactory(Interface): ... """A Python callable (e.g. classes) which is able to produce ... communication devices (e.g. messages). ... """ >>> alsoProvides(StandardMessage, ICommunicationFactory) >>> alsoProvides(StrongMessage, ICommunicationFactory) >>> ICommunicationFactory.implementedBy(StandardMessage) False >>> ICommunicationFactory.providedBy(StandardMessage) True >>> ICommunicationFactory.providedBy(StrongMessage) TrueThe documentation in zope.interface.interfaces describes in detail the various ways in which interfaces can be applied, inspected, and manipulated.
[size=5]Using Interfaces in Catalog Searches[/size]
In the previous section, we demonstrated how to use the catalog to search for objects by their portal_type, a string. This pattern is quite common, but has a few drawbacks:
- There can only ever be one content type installed with the same portal_type name. We can search for multiple portal types, but the code that searches needs to be aware of all such types in advance.
- Although it is uncommon, portal_type names can be changed.Interfaces are a better way to describe the semantic type of a content object. In Plone3, the object_provides catalog index can be used to search for objects providing a particular interface. This takes into account interfaces inherited from parent objects,as well as generalizations of specific interfaces provided.
Note that this index only stores the names of the interfaces an object held when it was being cataloged. Changes in code or ZCML may mean that an object's interfaces change after it has been indexed, in which case the catalog would not be aware of this until the object is reindexed.
>>> from Products.ATContentTypes.interface import ITextContent >>> results = catalog(object_provides=ITextContent.__identifier__) >>> sorted([r.getId for r in results]) ['favorites', 'fender', 'lp', 'pbass', 'strat', 'tele']In this example, we search for all standard text content. Interfaces for Plone's standard content types can be found in Products.ATContentTypes.interface.
Normally, the interfaces would be found in an interfaces module,but by historical accident, this name was already taken in the ATContentTypes package, so here had to use the name interface instead for its Zope 3 interfaces.