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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Created by GNU Texinfo 5.2, http://www.gnu.org/software/texinfo/ -->
<head>
<title>GNU Octave: Inheritance and Aggregation</title>
<meta name="description" content="GNU Octave: Inheritance and Aggregation">
<meta name="keywords" content="GNU Octave: Inheritance and Aggregation">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="index.html#Top" rel="start" title="Top">
<link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="Object-Oriented-Programming.html#Object-Oriented-Programming" rel="up" title="Object Oriented Programming">
<link href="GUI-Development.html#GUI-Development" rel="next" title="GUI Development">
<link href="Precedence-of-Objects.html#Precedence-of-Objects" rel="prev" title="Precedence of Objects">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.indentedblock {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smallindentedblock {margin-left: 3.2em; font-size: smaller}
div.smalllisp {margin-left: 3.2em}
kbd {font-style:oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nocodebreak {white-space:nowrap}
span.nolinebreak {white-space:nowrap}
span.roman {font-family:serif; font-weight:normal}
span.sansserif {font-family:sans-serif; font-weight:normal}
ul.no-bullet {list-style: none}
-->
</style>
</head>
<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">
<a name="Inheritance-and-Aggregation"></a>
<div class="header">
<p>
Previous: <a href="Overloading-Objects.html#Overloading-Objects" accesskey="p" rel="prev">Overloading Objects</a>, Up: <a href="Object-Oriented-Programming.html#Object-Oriented-Programming" accesskey="u" rel="up">Object Oriented Programming</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
</div>
<hr>
<a name="Inheritance-and-Aggregation-1"></a>
<h3 class="section">34.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>
<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>
<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.
</p>
<div class="example">
<pre class="example">octave:1> x = [some data vector];
octave:2> n = [some coefficient vector];
octave:3> y = filter (n, 1, x);
</pre></div>
<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.
</p>
<div class="example">
<pre class="verbatim">## -*- texinfo -*-
## @deftypefn {Function File} {} FIRfilter ()
## @deftypefnx {Function File} {} FIRfilter (@var{p})
## Create a 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 class="example">
</pre></div>
<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>
<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 objects from save files to
determine the inheritance structure.
</p>
<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>
<p>As before, we need a <code>display</code> method. A simple example might be
</p>
<div class="example">
<pre class="verbatim">function display (f)
display (f.polynomial);
endfunction
</pre><pre class="example">
</pre></div>
<p>Note that we have used the polynomial field of the struct to display
the filter coefficients.
</p>
<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.
</p>
<div class="example">
<pre class="example">octave:1> f = FIRfilter (polynomial ([1 1 1]/3))
f.polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
octave:2> class (f)
ans = FIRfilter
octave:3> isa (f,"FIRfilter")
ans = 1
octave:4> isa (f,"polynomial")
ans = 1
octave:5> struct (f)
ans =
{
polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
}
</pre></div>
<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.
</p>
<div 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 class="example">
</pre></div>
<p>The <code>"()"</code> case allows us to filter data using the polynomial provided
to the constructor.
</p>
<div class="example">
<pre class="example">octave:2> f = FIRfilter (polynomial ([1 1 1]/3));
octave:3> x = ones (5,1);
octave:4> y = f(x)
y =
0.33333
0.66667
1.00000
1.00000
1.00000
</pre></div>
<p>The <code>"."</code> case allows us to view the contents of the polynomial field.
</p>
<div class="example">
<pre class="example">octave:1> f = FIRfilter (polynomial ([1 1 1]/3));
octave:2> f.polynomial
ans = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2
</pre></div>
<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 writable.
</p>
<div 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 class="example">
</pre></div>
<p>So that
</p>
<div class="example">
<pre class="example">octave:6> f = FIRfilter ();
octave:7> f.polynomial = polynomial ([1 2 3]);
f.polynomial = 1 + 2 * X + 3 * X ^ 2
</pre></div>
<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
</p>
<div class="example">
<pre class="verbatim">## -*- texinfo -*-
## @deftypefn {Function File} {} FIRfilter ()
## @deftypefnx {Function File} {} FIRfilter (@var{p})
## Create a 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 class="example">
</pre></div>
<p>For our example, the remaining class methods remain unchanged.
</p>
<hr>
<div class="header">
<p>
Previous: <a href="Overloading-Objects.html#Overloading-Objects" accesskey="p" rel="prev">Overloading Objects</a>, Up: <a href="Object-Oriented-Programming.html#Object-Oriented-Programming" accesskey="u" rel="up">Object Oriented Programming</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>
|