summaryrefslogtreecommitdiff
path: root/doc/core/howto/components.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/core/howto/components.html')
-rw-r--r--doc/core/howto/components.html603
1 files changed, 603 insertions, 0 deletions
diff --git a/doc/core/howto/components.html b/doc/core/howto/components.html
new file mode 100644
index 0000000..b52e9e7
--- /dev/null
+++ b/doc/core/howto/components.html
@@ -0,0 +1,603 @@
+<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+<title>Twisted Documentation: Components: Interfaces and Adapters</title>
+<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
+ </head>
+
+ <body bgcolor="white">
+ <h1 class="title">Components: Interfaces and Adapters</h1>
+ <div class="toc"><ol><li><a href="#auto0">Interfaces and Components in Twisted code</a></li><ul><li><a href="#auto1">Components and Inheritance</a></li></ul></ol></div>
+ <div class="content">
+<span/>
+
+<p>Object oriented programming languages allow programmers to reuse portions of
+existing code by creating new <q>classes</q> of objects which subclass another
+class. When a class subclasses another, it is said to <em>inherit</em> all of its
+behaviour. The subclass can then <q>override</q> and <q>extend</q> the behavior
+provided to it by the superclass. Inheritance is very useful in many situations,
+but because it is so convenient to use, often becomes abused in large software
+systems, especially when multiple inheritance is involved. One solution is to
+use <em>delegation</em> instead of <q>inheritance</q> where appropriate.
+Delegation is simply the act of asking <em>another</em> object to perform a task
+for an object. To support this design pattern, which is often referred to as
+the <em>components</em> pattern because it involves many small interacting
+components, <em>interfaces</em> and <em>adapters</em> were created by the Zope
+3 team.</p>
+
+<p><q>Interfaces</q> are simply markers which objects can use to say <q>I
+implement this interface</q>. Other objects may then make requests like
+<q>Please give me an object which implements interface X for object type Y</q>.
+Objects which implement an interface for another object type are called
+<q>adapters</q>.</p>
+
+<p>The superclass-subclass relationship is said to be an <em>is-a</em> relationship.
+When designing object hierarchies, object modellers use subclassing when they
+can say that the subclass <em>is</em> the same class as the superclass. For
+example:</p>
+
+<pre class="python"><p class="py-linenumber"> 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">Shape</span>:
+ <span class="py-src-variable">sideLength</span> = <span class="py-src-number">0</span>
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">getSideLength</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">setSideLength</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">sideLength</span>):
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span> = <span class="py-src-variable">sideLength</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">area</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span>, <span class="py-src-string">&quot;Subclasses must implement area&quot;</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">Triangle</span>(<span class="py-src-parameter">Shape</span>):
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">area</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> (<span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span> * <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span>) / <span class="py-src-number">2</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">Square</span>(<span class="py-src-parameter">Shape</span>):
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">area</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span> * <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span>
+</pre>
+
+<p>In the above example, a Triangle <em>is-a</em> Shape, so it subclasses Shape,
+and a Square <em>is-a</em> Shape, so it also subclasses Shape.</p>
+
+<p>However, subclassing can get complicated, especially when Multiple
+Inheritance enters the picture. Multiple Inheritance allows a class to inherit
+from more than one base class. Software which relies heavily on inheritance
+often ends up having both very wide and very deep inheritance trees, meaning
+that one class inherits from many superclasses spread throughout the system.
+Since subclassing with Multiple Inheritance means <em>implementation
+inheritance</em>, locating a method's actual implementation and ensuring the
+correct method is actually being invoked becomes a challenge. For example:</p>
+
+<pre class="python"><p class="py-linenumber"> 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">Area</span>:
+ <span class="py-src-variable">sideLength</span> = <span class="py-src-number">0</span>
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">getSideLength</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">setSideLength</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">sideLength</span>):
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span> = <span class="py-src-variable">sideLength</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">area</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span>, <span class="py-src-string">&quot;Subclasses must implement area&quot;</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">Color</span>:
+ <span class="py-src-variable">color</span> = <span class="py-src-variable">None</span>
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">setColor</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">color</span>):
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">color</span> = <span class="py-src-variable">color</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">getColor</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">color</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">Square</span>(<span class="py-src-parameter">Area</span>, <span class="py-src-parameter">Color</span>):
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">area</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span> * <span class="py-src-variable">self</span>.<span class="py-src-variable">sideLength</span>
+</pre>
+
+<p>The reason programmers like using implementation inheritance is because it
+makes code easier to read since the implementation details of Area are in a
+separate place than the implementation details of Color. This is nice, because
+conceivably an object could have a color but not an area, or an area but not a
+color. The problem, though, is that Square is not really an Area or a Color, but
+has an area and color. Thus, we should really be using another object oriented
+technique called <em>composition</em>, which relies on delegation rather than
+inheritance to break code into small reusable chunks. Let us continue with the
+Multiple Inheritance example, though, because it is often used in practice.</p>
+
+<p>What if both the Color and the Area base class defined the same
+method, perhaps <code>calculate</code>? Where would the implementation
+come from? The implementation that is located
+for <code>Square().calculate()</code> depends on the method resolution
+order, or MRO, and can change when programmers change seemingly
+unrelated things by refactoring classes in other parts of the system,
+causing obscure bugs. Our first thought might be to change the
+calculate method name to avoid name clashes, to
+perhaps <code>calculateArea</code> and <code>calculateColor</code>.
+While explicit, this change could potentially require a large number
+of changes throughout a system, and is error-prone, especially when
+attempting to integrate two systems which you didn't write.</p>
+
+<p>Let's imagine another example. We have an electric appliance, say a hair
+dryer. The hair dryer is American voltage. We have two electric sockets, one of
+them an American 120 Volt socket, and one of them a United Kingdom 240 Volt socket. If
+we plug the hair dryer into the 240 Volt socket, it is going to expect 120 Volt
+current and errors will result. Going back and changing the hair dryer to
+support both <code>plug120Volt</code> and <code>plug240Volt</code> methods would
+be tedious, and what if we decided we needed to plug the hair dryer into yet
+another type of socket? For example:</p>
+
+<pre class="python"><p class="py-linenumber"> 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">HairDryer</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">plug</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">socket</span>):
+ <span class="py-src-keyword">if</span> <span class="py-src-variable">socket</span>.<span class="py-src-variable">voltage</span>() == <span class="py-src-number">120</span>:
+ <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;I was plugged in properly and am operating.&quot;</span>
+ <span class="py-src-keyword">else</span>:
+ <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;I was plugged in improperly and &quot;</span>
+ <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;now you have no hair dryer any more.&quot;</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">AmericanSocket</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-number">120</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">UKSocket</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-number">240</span>
+</pre>
+
+<p>Given these classes, the following operations can be performed:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; hd = HairDryer()
+&gt;&gt;&gt; am = AmericanSocket()
+&gt;&gt;&gt; hd.plug(am)
+I was plugged in properly and am operating.
+&gt;&gt;&gt; uk = UKSocket()
+&gt;&gt;&gt; hd.plug(uk)
+I was plugged in improperly and
+now you have no hair dryer any more.
+</pre>
+
+<p>We are going to attempt to solve this problem by writing an Adapter for
+the <code>UKSocket</code> which converts the voltage for use with an American
+hair dryer. An Adapter is a class which is constructed with one and only one
+argument, the <q>adaptee</q> or <q>original</q> object. In this example, we
+will show all code involved for clarity:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">AdaptToAmericanSocket</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">original</span>):
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span> = <span class="py-src-variable">original</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span>.<span class="py-src-variable">voltage</span>() / <span class="py-src-number">2</span>
+</pre>
+
+<p>Now, we can use it as so:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; hd = HairDryer()
+&gt;&gt;&gt; uk = UKSocket()
+&gt;&gt;&gt; adapted = AdaptToAmericanSocket(uk)
+&gt;&gt;&gt; hd.plug(adapted)
+I was plugged in properly and am operating.
+</pre>
+
+<p>So, as you can see, an adapter can 'override' the original implementation. It
+can also 'extend' the interface of the original object by providing methods the
+original object did not have. Note that an Adapter must explicitly delegate any
+method calls it does not wish to modify to the original, otherwise the Adapter
+cannot be used in places where the original is expected. Usually this is not a
+problem, as an Adapter is created to conform an object to a particular interface
+and then discarded.</p>
+
+<h2>Interfaces and Components in Twisted code<a name="auto0"/></h2>
+
+<p>Adapters are a useful way of using multiple classes to factor code into
+discrete chunks. However, they are not very interesting without some more
+infrastructure. If each piece of code which wished to use an adapted object had
+to explicitly construct the adapter itself, the coupling between components
+would be too tight. We would like to achieve <q>loose coupling</q>, and this is
+where <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.python.components.html" title="twisted.python.components">twisted.python.components</a></code> comes in.</p>
+
+<p>First, we need to discuss Interfaces in more detail. As we mentioned
+earlier, an Interface is nothing more than a class which is used as a marker.
+Interfaces should be subclasses of <code>zope.interface.Interface</code>, and
+have a very odd look to python programmers not used to them:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+7
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">IAmericanSocket</span>(<span class="py-src-parameter">Interface</span>):
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>():
+ <span class="py-src-string">&quot;&quot;&quot;
+ Return the voltage produced by this socket object, as an integer.
+ &quot;&quot;&quot;</span>
+</pre>
+
+<p>Notice how it looks just like a regular class definition, other than
+inheriting from <code>Interface</code>? However, the method definitions inside
+the class block do not have any method body! Since Python does not have any
+native language-level support for Interfaces like Java does, this is what
+distinguishes an Interface definition from a Class.</p>
+
+<p>Now that we have a defined Interface, we can talk about objects using terms
+like this: <q>The <code>AmericanSocket</code> class implements the <code>IAmericanSocket</code> interface</q> and <q>Please give me an object which
+adapts <code>UKSocket</code> to the <code>IAmericanSocket</code>
+interface</q>. We can make <em>declarations</em> about what interfaces a certain
+class implements, and we can request adapters which implement a certain
+interface for a specific class.</p>
+
+<p>Let's look at how we declare that a class implements an interface:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+7
+8
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">AmericanSocket</span>:
+
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IAmericanSocket</span>)
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-number">120</span>
+</pre>
+
+<p>So, to declare that a class implements an interface, we simply
+call <code>zope.interface.implements</code> at the class level.</p>
+
+<p>Now, let's say we want to rewrite
+the <code>AdaptToAmericanSocket</code> class as a real adapter. In
+this case we also specify it as
+implementing <code>IAmericanSocket</code>:</p>
+
+<pre class="python"><p class="py-linenumber"> 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">AdaptToAmericanSocket</span>:
+
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IAmericanSocket</span>)
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">original</span>):
+ <span class="py-src-string">&quot;&quot;&quot;
+ Pass the original UKSocket object as original
+ &quot;&quot;&quot;</span>
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span> = <span class="py-src-variable">original</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span>.<span class="py-src-variable">voltage</span>() / <span class="py-src-number">2</span>
+</pre>
+
+<p>Notice how we placed the implements declaration on this adapter class. So
+far, we have not achieved anything by using components other than requiring us
+to type more. In order for components to be useful, we must use the
+<em>component registry</em>. Since <code>AdaptToAmericanSocket</code>
+implements
+<code>IAmericanSocket</code> and regulates the voltage of a
+<code>UKSocket</code> object, we can register
+<code>AdaptToAmericanSocket</code> as an <code>IAmericanSocket</code> adapter
+for the <code>UKSocket</code> class. It is easier to see how this is
+done in code than to describe it:</p>
+
+<pre class="python"><p class="py-linenumber"> 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>, <span class="py-src-variable">implements</span>
+<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">components</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">IAmericanSocket</span>(<span class="py-src-parameter">Interface</span>):
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>():
+ <span class="py-src-string">&quot;&quot;&quot;Return the voltage produced by this socket object, as an integer.
+ &quot;&quot;&quot;</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">AmericanSocket</span>:
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IAmericanSocket</span>)
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-number">120</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">UKSocket</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-number">240</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">AdaptToAmericanSocket</span>:
+
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IAmericanSocket</span>)
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">original</span>):
+ <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span> = <span class="py-src-variable">original</span>
+
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">voltage</span>(<span class="py-src-parameter">self</span>):
+ <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">original</span>.<span class="py-src-variable">voltage</span>() / <span class="py-src-number">2</span>
+
+<span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(
+ <span class="py-src-variable">AdaptToAmericanSocket</span>,
+ <span class="py-src-variable">UKSocket</span>,
+ <span class="py-src-variable">IAmericanSocket</span>)
+</pre>
+
+<p>Now, if we run this script in the interactive interpreter, we can discover a
+little more about how to use components. The first thing we can do is discover
+whether an object implements an interface or not:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; IAmericanSocket.implementedBy(AmericanSocket)
+True
+&gt;&gt;&gt; IAmericanSocket.implementedBy(UKSocket)
+False
+&gt;&gt;&gt; am = AmericanSocket()
+&gt;&gt;&gt; uk = UKSocket()
+&gt;&gt;&gt; IAmericanSocket.providedBy(am)
+True
+&gt;&gt;&gt; IAmericanSocket.providedBy(uk)
+False
+</pre>
+
+<p>As you can see, the <code>AmericanSocket</code> instance claims to
+implement <code>IAmericanSocket</code>, but the <code>UKSocket</code>
+does not. If we wanted to use the <code>HairDryer</code> with the <code>AmericanSocket</code>, we could know that it would be safe to do so by
+checking whether it implements <code>IAmericanSocket</code>. However, if we
+decide we want to use <code>HairDryer</code> with a <code>UKSocket</code>
+instance, we must <em>adapt</em> it to <code>IAmericanSocket</code> before
+doing so. We use the interface object to do this:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; IAmericanSocket(uk)
+&lt;__main__.AdaptToAmericanSocket instance at 0x1a5120&gt;
+</pre>
+
+<p>When calling an interface with an object as an argument, the interface
+looks in the adapter registry for an adapter which implements the interface for
+the given instance's class. If it finds one, it constructs an instance of the
+Adapter class, passing the constructor the original instance, and returns it.
+Now the <code>HairDryer</code> can safely be used with the adapted <code>UKSocket</code>. But what happens if we attempt to adapt an object
+which already implements <code>IAmericanSocket</code>? We simply get back the
+original instance:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; IAmericanSocket(am)
+&lt;__main__.AmericanSocket instance at 0x36bff0&gt;
+</pre>
+
+<p>So, we could write a new <q>smart</q> <code>HairDryer</code> which
+automatically looked up an adapter for the socket you tried to plug it into:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">HairDryer</span>:
+ <span class="py-src-keyword">def</span> <span class="py-src-identifier">plug</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">socket</span>):
+ <span class="py-src-variable">adapted</span> = <span class="py-src-variable">IAmericanSocket</span>(<span class="py-src-variable">socket</span>)
+ <span class="py-src-keyword">assert</span> <span class="py-src-variable">adapted</span>.<span class="py-src-variable">voltage</span>() == <span class="py-src-number">120</span>, <span class="py-src-string">&quot;BOOM&quot;</span>
+ <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;I was plugged in properly and am operating&quot;</span>
+</pre>
+
+<p>Now, if we create an instance of our new <q>smart</q> <code>HairDryer</code>
+and attempt to plug it in to various sockets, the <code>HairDryer</code> will
+adapt itself automatically depending on the type of socket it is plugged in
+to:</p>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; am = AmericanSocket()
+&gt;&gt;&gt; uk = UKSocket()
+&gt;&gt;&gt; hd = HairDryer()
+&gt;&gt;&gt; hd.plug(am)
+I was plugged in properly and am operating
+&gt;&gt;&gt; hd.plug(uk)
+I was plugged in properly and am operating
+</pre>
+
+<p>Voila; the magic of components.</p>
+
+<h3>Components and Inheritance<a name="auto1"/></h3>
+
+<p>If you inherit from a class which implements some interface, and your new
+subclass declares that it implements another interface, the implements will be
+inherited by default.</p>
+
+<p>For example, <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.spread.pb.Root.html" title="twisted.spread.pb.Root">pb.Root</a></code> is a class
+which implements <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.spread.pb.IPBRoot.html" title="twisted.spread.pb.IPBRoot">IPBRoot</a></code>. This interface indicates that an
+object has remotely-invokable methods and can be used as the initial object
+served by a new Broker instance. It has an <code>implements</code> setting
+like:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">Root</span>(<span class="py-src-parameter">Referenceable</span>):
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IPBRoot</span>)
+</pre>
+
+<p>Suppose you have your own class which implements your
+<code>IMyInterface</code> interface:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+7
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>, <span class="py-src-variable">Interface</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">IMyInterface</span>(<span class="py-src-parameter">Interface</span>):
+ <span class="py-src-keyword">pass</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">MyThing</span>:
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IMyInterface</span>)
+</pre>
+
+<p>Now if you want to make this class inherit from <code>pb.Root</code>,
+the interfaces code will automatically determine that it also implements
+<code>IPBRoot</code>:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+7
+8
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">spread</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">pb</span>
+<span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>, <span class="py-src-variable">Interface</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">IMyInterface</span>(<span class="py-src-parameter">Interface</span>):
+ <span class="py-src-keyword">pass</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">MyThing</span>(<span class="py-src-parameter">pb</span>.<span class="py-src-parameter">Root</span>):
+ <span class="py-src-variable">implements</span>(<span class="py-src-variable">IMyInterface</span>)
+</pre>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; from twisted.spread.flavors import IPBRoot
+&gt;&gt;&gt; IPBRoot.implementedBy(MyThing)
+True
+</pre>
+
+<p>If you want <code>MyThing</code> to inherit from <code>pb.Root</code> but <em>not</em> implement <code>IPBRoot</code> like <code>pb.Root</code> does,
+use <code>implementOnly</code>:</p>
+
+<pre class="python"><p class="py-linenumber">1
+2
+3
+4
+5
+6
+7
+8
+</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">spread</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">pb</span>
+<span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implementsOnly</span>, <span class="py-src-variable">Interface</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">IMyInterface</span>(<span class="py-src-parameter">Interface</span>):
+ <span class="py-src-keyword">pass</span>
+
+<span class="py-src-keyword">class</span> <span class="py-src-identifier">MyThing</span>(<span class="py-src-parameter">pb</span>.<span class="py-src-parameter">Root</span>):
+ <span class="py-src-variable">implementsOnly</span>(<span class="py-src-variable">IMyInterface</span>)
+</pre>
+
+<pre class="python-interpreter" xml:space="preserve">
+&gt;&gt;&gt; from twisted.spread.pb import IPBRoot
+&gt;&gt;&gt; IPBRoot.implementedBy(MyThing)
+False
+</pre>
+
+</div>
+
+ <p><a href="index.html">Index</a></p>
+ <span class="version">Version: 12.1.0</span>
+ </body>
+</html> \ No newline at end of file