Changeset 86

Show
Ignore:
Timestamp:
01/15/07 00:19:22 (2 years ago)
Author:
KirkMcDonald
Message:

Moved inheritance-wrapping docs to their own page.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/html_doc/basics.html

    r64 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/celerid.html

    r64 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/class_wrapping.html

    r64 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="navcur" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
     
    106107</dl> 
    107108 
    108 <h3><a class="anchor" name="inheritance">Inheritance</a></h3> 
    109  
    110 <p>If you wrap both a class and a child of that class, Pyd is smart enough to make the resulting Python classes have a parent-child relationship. Any methods of the parent class will automatically be available to the child class. If the child class overloads any of those methods, it is important that the user wrap them in the module's init function. For example:</p> 
    111  
    112 <pre class="code"><span class="keyword">import</span> std.stdio; 
    113  
    114 <span class="keyword">class</span> Base { 
    115     <span class="keyword">void</span> foo() { writefln(<span class="string">"Base.foo"</span>); } 
    116     <span class="keyword">void</span> bar() { writefln(<span class="string">"Base.bar"</span>); } 
    117 } 
    118  
    119 <span class="keyword">class</span> Derived : Base { 
    120     <span class="keyword">void</span> foo() { writefln(<span class="string">"Derived.foo"</span>); } 
    121 }</pre> 
    122  
    123 <p>These would be exposed to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    124  
    125 <pre class="code">wrapped_class!(Base) b; 
    126 b.def!(Base.foo); 
    127 b.def!(Base.bar); 
    128 finalize_class(b); 
    129  
    130 wrapped_class!(Derived) d; 
    131 d.def!(Derived.foo); 
    132 finalize_class(d);</pre> 
    133  
    134 <p>When used in Python, we get the expected behavior:</p> 
    135  
    136 <pre class="code">&gt;&gt;&gt; issubclass(Derived, Base) 
    137 True 
    138 &gt;&gt;&gt; b = Base() 
    139 &gt;&gt;&gt; d = Derived() 
    140 &gt;&gt;&gt; b.foo() 
    141 Base.foo 
    142 &gt;&gt;&gt; b.bar() 
    143 Base.bar 
    144 &gt;&gt;&gt; d.foo() 
    145 Derived.foo 
    146 &gt;&gt;&gt; d.bar() 
    147 Base.bar</pre> 
    148  
    149 <p>There is one weakness in the default behavior. Take a function like the following:</p> 
    150  
    151 <pre class="code"><span class="keyword">void</span> polymorphic_call(Base b) { 
    152     b.foo(); 
    153 }</pre> 
    154  
    155 <p>And in Python:</p> 
    156  
    157 <pre class="code"><span class="keyword">class</span> PyClass(Base): 
    158     <span class="keyword">def</span> foo(self): 
    159         <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
    160  
    161 &gt;&gt;&gt; p = PyClass() 
    162 &gt;&gt;&gt; polymorphic_call(p) 
    163 Base.foo</pre> 
    164  
    165 <p>Optimally, we would want <code>polymorphic_call</code> to call PyClass.foo. This requires some additional work on the D side of things. To get this behavior, then rather than expose Base directly, we must expose a wrapper class:</p> 
    166  
    167 <pre class="code"><span class="keyword">class</span> BaseWrap : Base { 
    168     <span class="keyword">mixin</span> OverloadShim; 
    169     <span class="keyword">void</span> foo() { 
    170         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    171     } 
    172     <span class="keyword">void</span> bar() { 
    173         get_overload(&amp;<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 
    174     } 
    175 }</pre> 
    176  
    177 <p>The <code>OverloadShim</code> template has but a single member, the <code>get_overload</code> function.</p> 
    178  
    179 <dl> 
    180 <dt><code>ReturnType!(dg_t) get_overload(<span class="t_arg">dg_t</span>, <span class="t_arg">T ...</span>) (dg_t <span class="arg">dg</span>, char[] <span class="arg">name</span>, T <span class="arg">t</span>);</code></dt> 
    181 <dd><ul> 
    182     <li><span class="arg">dg</span> should be a delegate to the parent class's method.</li> 
    183     <li><span class="arg">name</span> should be the name of the method as Python understands it to be. <i>(There's no efficient way to derive this automatically based on only the delegate.)</i></li> 
    184     <li><span class="arg">t</span> is a tuple argument. These arguments will be passed on to the actual function call, be it the parent class's implementation or a Python subclass's implementation.</li> 
    185 </ul></dd> 
    186 </dl> 
    187  
    188 <p><code>get_overload</code> returns whatever the method does.</p> 
    189  
    190 <p>Now, we must replace the old wrapping of Base with this:</p> 
    191  
    192 <pre class="code">wrapped_class!(BaseWrap, <span class="string">"Base"</span>) w; 
    193 w.def!(BaseWrap.foo); 
    194 w.def!(BaseWrap.bar); 
    195 finalize_class(w);</pre> 
    196  
    197 <p>Now our subclass will perform just like we expect:</p> 
    198  
    199 <pre class="code">&gt;&gt;&gt; p = PyClass() 
    200 &gt;&gt;&gt; polymorphic_call(p) 
    201 PyClass.foo</pre> 
    202  
    203109<h3><a class="anchor" name="examples">Examples</a></h3> 
    204110 
  • trunk/html_doc/conversion.html

    r57 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/credits.html

    r57 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/except_wrapping.html

    r57 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="navcur" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/func_wrapping.html

    r64 r86  
    1717<a class="navcur" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/index.html

    r64 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/install.html

    r62 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/pydobject.html

    r57 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/struct_wrapping.html

    r59 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="navcur" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/html_doc/vsboost.html

    r57 r86  
    1717<a class="nav" href="func_wrapping.html">Function wrapping</a><br /> 
    1818<a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 
     19<a class="nav" href="inherit.html">Inheritance</a><br /> 
    1920<a class="nav" href="struct_wrapping.html">Struct wrapping</a><br /> 
    2021<a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 
  • trunk/raw_html/class_wrapping.html

    r64 r86  
    9191</dl> 
    9292 
    93 <h3><a class="anchor" name="inheritance">Inheritance</a></h3> 
    94  
    95 <p>If you wrap both a class and a child of that class, Pyd is smart enough to make the resulting Python classes have a parent-child relationship. Any methods of the parent class will automatically be available to the child class. If the child class overloads any of those methods, it is important that the user wrap them in the module's init function. For example:</p> 
    96  
    97 <pre class="code"><span class="keyword">import</span> std.stdio; 
    98  
    99 <span class="keyword">class</span> Base { 
    100     <span class="keyword">void</span> foo() { writefln(<span class="string">"Base.foo"</span>); } 
    101     <span class="keyword">void</span> bar() { writefln(<span class="string">"Base.bar"</span>); } 
    102 } 
    103  
    104 <span class="keyword">class</span> Derived : Base { 
    105     <span class="keyword">void</span> foo() { writefln(<span class="string">"Derived.foo"</span>); } 
    106 }</pre> 
    107  
    108 <p>These would be exposed to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    109  
    110 <pre class="code">wrapped_class!(Base) b; 
    111 b.def!(Base.foo); 
    112 b.def!(Base.bar); 
    113 finalize_class(b); 
    114  
    115 wrapped_class!(Derived) d; 
    116 d.def!(Derived.foo); 
    117 finalize_class(d);</pre> 
    118  
    119 <p>When used in Python, we get the expected behavior:</p> 
    120  
    121 <pre class="code">&gt;&gt;&gt; issubclass(Derived, Base) 
    122 True 
    123 &gt;&gt;&gt; b = Base() 
    124 &gt;&gt;&gt; d = Derived() 
    125 &gt;&gt;&gt; b.foo() 
    126 Base.foo 
    127 &gt;&gt;&gt; b.bar() 
    128 Base.bar 
    129 &gt;&gt;&gt; d.foo() 
    130 Derived.foo 
    131 &gt;&gt;&gt; d.bar() 
    132 Base.bar</pre> 
    133  
    134 <p>There is one weakness in the default behavior. Take a function like the following:</p> 
    135  
    136 <pre class="code"><span class="keyword">void</span> polymorphic_call(Base b) { 
    137     b.foo(); 
    138 }</pre> 
    139  
    140 <p>And in Python:</p> 
    141  
    142 <pre class="code"><span class="keyword">class</span> PyClass(Base): 
    143     <span class="keyword">def</span> foo(self): 
    144         <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
    145  
    146 &gt;&gt;&gt; p = PyClass() 
    147 &gt;&gt;&gt; polymorphic_call(p) 
    148 Base.foo</pre> 
    149  
    150 <p>Optimally, we would want <code>polymorphic_call</code> to call PyClass.foo. This requires some additional work on the D side of things. To get this behavior, then rather than expose Base directly, we must expose a wrapper class:</p> 
    151  
    152 <pre class="code"><span class="keyword">class</span> BaseWrap : Base { 
    153     <span class="keyword">mixin</span> OverloadShim; 
    154     <span class="keyword">void</span> foo() { 
    155         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    156     } 
    157     <span class="keyword">void</span> bar() { 
    158         get_overload(&amp;<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 
    159     } 
    160 }</pre> 
    161  
    162 <p>The <code>OverloadShim</code> template has but a single member, the <code>get_overload</code> function.</p> 
    163  
    164 <dl> 
    165 <dt><code>ReturnType!(dg_t) get_overload(<span class="t_arg">dg_t</span>, <span class="t_arg">T ...</span>) (dg_t <span class="arg">dg</span>, char[] <span class="arg">name</span>, T <span class="arg">t</span>);</code></dt> 
    166 <dd><ul> 
    167     <li><span class="arg">dg</span> should be a delegate to the parent class's method.</li> 
    168     <li><span class="arg">name</span> should be the name of the method as Python understands it to be. <i>(There's no efficient way to derive this automatically based on only the delegate.)</i></li> 
    169     <li><span class="arg">t</span> is a tuple argument. These arguments will be passed on to the actual function call, be it the parent class's implementation or a Python subclass's implementation.</li> 
    170 </ul></dd> 
    171 </dl> 
    172  
    173 <p><code>get_overload</code> returns whatever the method does.</p> 
    174  
    175 <p>Now, we must replace the old wrapping of Base with this:</p> 
    176  
    177 <pre class="code">wrapped_class!(BaseWrap, <span class="string">"Base"</span>) w; 
    178 w.def!(BaseWrap.foo); 
    179 w.def!(BaseWrap.bar); 
    180 finalize_class(w);</pre> 
    181  
    182 <p>Now our subclass will perform just like we expect:</p> 
    183  
    184 <pre class="code">&gt;&gt;&gt; p = PyClass() 
    185 &gt;&gt;&gt; polymorphic_call(p) 
    186 PyClass.foo</pre> 
    187  
    18893<h3><a class="anchor" name="examples">Examples</a></h3> 
    18994 
  • trunk/raw_html/header_template.html

    r62 r86  
    88<a class="%(func_wrapping)s" href="func_wrapping.html">Function wrapping</a><br /> 
    99<a class="%(class_wrapping)s" href="class_wrapping.html">Class wrapping</a><br /> 
     10<a class="%(inherit)s" href="inherit.html">Inheritance</a><br /> 
    1011<a class="%(struct_wrapping)s" href="struct_wrapping.html">Struct wrapping</a><br /> 
    1112<a class="%(except_wrapping)s" href="except_wrapping.html">Exception wrapping</a><br />