Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 3e60ff9d4d6f58c8fbd17208f14089fa > files > 234

octave-doc-3.2.3-3mdv2010.0.i586.rpm

<html lang="en">
<head>
<title>Inheritance and Aggregation - Untitled</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Untitled">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Object-Oriented-Programming.html#Object-Oriented-Programming" title="Object Oriented Programming">
<link rel="prev" href="Overloading-Objects.html#Overloading-Objects" title="Overloading Objects">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
  pre.display { font-family:inherit }
  pre.format  { font-family:inherit }
  pre.smalldisplay { font-family:inherit; font-size:smaller }
  pre.smallformat  { font-family:inherit; font-size:smaller }
  pre.smallexample { font-size:smaller }
  pre.smalllisp    { font-size:smaller }
  span.sc    { font-variant:small-caps }
  span.roman { font-family:serif; font-weight:normal; } 
  span.sansserif { font-family:sans-serif; font-weight:normal; } 
--></style>
</head>
<body>
<div class="node">
<a name="Inheritance-and-Aggregation"></a>
<p>
Previous:&nbsp;<a rel="previous" accesskey="p" href="Overloading-Objects.html#Overloading-Objects">Overloading Objects</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Object-Oriented-Programming.html#Object-Oriented-Programming">Object Oriented Programming</a>
<hr>
</div>

<h3 class="section">33.5 Inheritance and Aggregation</h3>

<p>Using classes to build new classes is supported by octave through the
use of both inheritance and aggregation.

   <p>Class inheritance is provided by octave using the <code>class</code>
function in the class constructor.  As in the case of the polynomial
class, the octave programmer will create a struct that contains the
data fields required by the class, and then call the class function to
indicate that an object is to be created from the struct.  Creating a
child of an existing object is done by creating an object of the
parent class and providing that object as the third argument of the
class function.

   <p>This is easily demonstrated by example.  Suppose the programmer needs
an FIR filter, i.e. a filter with a numerator polynomial but a unity
denominator polynomial.  In traditional octave programming, this would
be performed as follows.

<pre class="example">     octave:1&gt; x = [some data vector];
     octave:2&gt; n = [some coefficient vector];
     octave:3&gt; y = filter (n, 1, x);
</pre>
   <p>The equivalent class could be implemented in a class directory
@FIRfilter that is on the octave path.  The constructor is a file
FIRfilter.m in the class directory.

<pre class="example"><pre class="verbatim">     ## -*- texinfo -*-
     ## @deftypefn {Function File} {} FIRfilter ()
     ## @deftypefnx {Function File} {} FIRfilter (@var{p})
     ## Creates an FIR filter with polynomial @var{p} as
     ## coefficient vector.
     ##
     ## @end deftypefn
     
     function f = FIRfilter (p)
     
       f.polynomial = [];
       if (nargin == 0)
         p = @polynomial ([1]);
       elseif (nargin == 1)
         if (!isa (p, "polynomial"))
           error ("FIRfilter: expecting polynomial as input argument");
         endif
       else
         print_usage ();
       endif
       f = class (f, "FIRfilter", p);
     endfunction
</pre>
</pre>
   <p>As before, the leading comments provide command-line documentation for
the class constructor.  This constructor is very similar to the
polynomial class constructor, except that we pass a polynomial object
as the third argument to the class function, telling octave that the
FIRfilter class will be derived from the polynomial class.  Our FIR
filter does not have any data fields, but we must provide a struct to
the <code>class</code> function.  The <code>class</code> function will add an
element named polynomial to the object struct, so we simply add a
dummy element named polynomial as the first line of the constructor. 
This dummy element will be overwritten by the class function.

   <p>Note further that all our examples provide for the case in which no
arguments are supplied.  This is important since octave will call the
constructor with no arguments when loading ojects from save files to
determine the inheritance structure.

   <p>A class may be a child of more than one class (see the documentation
for the <code>class</code> function), and inheritance may be nested.  There
is no limitation to the number of parents or the level of nesting
other than memory or other physical issues.

   <p>As before, we need a <code>display</code> method.  A simple example might be

<pre class="example"><pre class="verbatim">     function display (f)
     
       display(f.polynomial);
     
     endfunction
     
</pre>
</pre>
   <p>Note that we have used the polynomial field of the struct to display
the filter coefficients.

   <p>Once we have the class constructor and display method, we may create
an object by calling the class constructor.  We may also check the
class type and examine the underlying structure.

<pre class="example">     octave:1&gt; f=FIRfilter(polynomial([1 1 1]/3))
     f.polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
     octave:2&gt; class(f)
     ans = FIRfilter
     octave:3&gt; isa(f,"FIRfilter")
     ans =  1
     octave:4&gt; isa(f,"polynomial")
     ans =  1
     octave:5&gt; struct(f)
     ans =
     {
     polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
     }
</pre>
   <p>We only need to define a method to actually process data with our
filter and our class is usable.  It is also useful to provide a means
of changing the data stored in the class.  Since the fields in the
underlying struct are private by default, we could provide a mechanism
to access the fields.  The <code>subsref</code> method may be used for both.

<pre class="example"><pre class="verbatim">     function out = subsref (f, x)
       switch x.type
         case "()"
           n = f.polynomial;
           out = filter(n.poly, 1, x.subs{1});
         case "."
           fld = x.subs;
           if (strcmp (fld, "polynomial"))
             out = f.polynomial;
           else
             error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
           endif
         otherwise
           error ("@FIRfilter/subsref: invalid subscript type for FIR filter");
       endswitch
     endfunction
</pre>
</pre>
   <p>The "()" case allows us to filter data using the polynomial provided
to the constructor.

<pre class="example">     octave:2&gt; f=FIRfilter(polynomial([1 1 1]/3));
     octave:3&gt; x=ones(5,1);
     octave:4&gt; y=f(x)
     y =
     
        0.33333
        0.66667
        1.00000
        1.00000
        1.00000
</pre>
   <p>The "." case allows us to view the contents of the polynomial field.

<pre class="example">     octave:1&gt; f=FIRfilter(polynomial([1 1 1]/3));
     octave:2&gt; f.polynomial
     ans = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
</pre>
   <p>In order to change the contents of the object, we need to define a
<code>subsasgn</code> method.  For example, we may make the polynomial field
publicly writeable.

<pre class="example"><pre class="verbatim">     function out = subsasgn (f, index, val)
       switch (index.type)
         case "."
           fld = index.subs;
           if (strcmp (fld, "polynomial"))
             out = f;
             out.polynomial = val;
           else
             error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
           endif
         otherwise
           error ("FIRfilter/subsagn: Invalid index type")
       endswitch
     endfunction
</pre>
</pre>
   <p>So that

<pre class="example">     octave:6&gt; f=FIRfilter();
     octave:7&gt; f.polynomial = polynomial([1 2 3]);
     f.polynomial = 1 + 2 * X + 3 * X ^ 2
</pre>
   <p>Defining the FIRfilter class as a child of the polynomial class
implies that and FIRfilter object may be used any place that a
polynomial may be used.  This is not a normal use of a filter, so that
aggregation may be a more sensible design approach.  In this case, the
polynomial is simply a field in the class structure.  A class
constructor for this case might be

<pre class="example"><pre class="verbatim">     ## -*- texinfo -*-
     ## @deftypefn {Function File} {} FIRfilter ()
     ## @deftypefnx {Function File} {} FIRfilter (@var{p})
     ## Creates an FIR filter with polynomial @var{p} as
     ## coefficient vector.
     ##
     ## @end deftypefn
     
     function f = FIRfilter (p)
     
       if (nargin == 0)
         f.polynomial = @polynomial ([1]);
       elseif (nargin == 1)
         if (isa (p, "polynomial"))
           f.polynomial = p;
         else
           error ("FIRfilter: expecting polynomial as input argument");
         endif
       else
         print_usage ();
       endif
       f = class (f, "FIRfilter");
     endfunction
</pre>
</pre>
   <p>For our example, the remaining class methods remain unchanged.

<!-- DO NOT EDIT!  Generated automatically by munge-texi. -->
<!-- Copyright (C) 1996, 1997, 1999, 2000, 2002, 2007, 2008, 2009 John W. Eaton -->
<!-- This file is part of Octave. -->
<!-- Octave is free software; you can redistribute it and/or modify it -->
<!-- under the terms of the GNU General Public License as published by the -->
<!-- Free Software Foundation; either version 3 of the License, or (at -->
<!-- your option) any later version. -->
<!-- Octave is distributed in the hope that it will be useful, but WITHOUT -->
<!-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -->
<!-- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License -->
<!-- for more details. -->
<!-- You should have received a copy of the GNU General Public License -->
<!-- along with Octave; see the file COPYING.  If not, see -->
<!-- <http://www.gnu.org/licenses/>. -->
   </body></html>