# HG changeset patch # User Rik # Date 1452752335 28800 # Node ID 220506787b9388de99bbb1c76bbec63aebfc41f3 # Parent 31d41418fa579872a7bf5ad82462a3fd076dd554 doc: Overhaul chapter on old-style Object Oriented Programming. * oop.txi: Clean up language which had some odd phrasings. Use the neutral third person rather than "we/our". Eliminate extra spaces before code in @example blocks. Wrap lines at 80 characters. diff -r 31d41418fa57 -r 220506787b93 doc/interpreter/oop.txi --- a/doc/interpreter/oop.txi Wed Jan 13 17:11:56 2016 -0800 +++ b/doc/interpreter/oop.txi Wed Jan 13 22:18:55 2016 -0800 @@ -24,16 +24,16 @@ @node Object Oriented Programming @chapter Object Oriented Programming -Octave includes the capability to include user classes, including the -features of operator and function overloading. Equally a user class -can be used to encapsulate certain properties of the class so that -they cannot be altered accidentally and can be set up to address the -issue of class precedence in mixed class operations. +Octave includes the capability to create user-defined classes, including the +capabilities of operator and function overloading. Classes can protect +internal properties so they can not be altered accidentally which facilitates +data encapsulation. In addition, rules can be created to address the issue +of class precedence in mixed class operations. -This chapter discussions the means of constructing a user class with -the example of a polynomial class, how to query and set the properties -of this class, together with the means to overload operators and -functions. +This chapter discusses the means of constructing a user class, how to query and +set the properties of a class, and how to overload operators and functions. +Throughout this chapter real code examples are given using a class designed +for polynomials. @menu * Creating a Class:: @@ -46,12 +46,12 @@ @node Creating a Class @section Creating a Class -We use in the following text a polynomial class to demonstrate the use -of object oriented programming within Octave. This class was chosen as -it is simple, and so doesn't distract unnecessarily from the -discussion of the programming features of Octave. However, even still -a small understand of the polynomial class itself is necessary to -fully grasp the techniques described. +This chapter illustrates user-defined classes and object oriented programming +through a custom class designed for polynomials. This class was chosen as it +is simple, and therefore doesn't distract unnecessarily from the discussion of +the programming features of Octave. Even so, a bit of background on the goals +of the polynomial class is necessary before the syntax and techniques of Octave +object oriented programming are introduced. The polynomial class is used to represent polynomials of the form @tex @@ -80,48 +80,47 @@ a = [a0, a1, a2, @dots{}, an]; @end example -We therefore now have sufficient information about the requirements of -the class constructor for our polynomial class to write it. All object -oriented classes in Octave, must be contained with a directory taking -the name of the class, prepended with the @@ symbol. For example, with -our polynomial class, we would place the methods defining the class in -the @@polynomial directory. +This is is a sufficient specification to begin writing the constructor for the +polynomial class. All object oriented classes in Octave must be located in a +directory that has the name of the class prepended with the @@ symbol. For +example, the polynomial class will have all of its methods defined in the +@@polynomial directory. -The constructor of the class, must have the name of the class itself -and so in our example the constructor with have the name -@file{@@polynomial/polynomial.m}. Also ideally when the constructor is -called with no arguments to should return a value object. So for example -our polynomial might look like +The constructor for the class must be the name of the class itself; in this +example the constructor has the name @file{@@polynomial/polynomial.m}. +Ideally, even when the constructor is called with no arguments it should return +a valid object. A constructor for the polynomial class might look like @example @EXAMPLEFILE(@polynomial/polynomial.m) @end example -Note that the return value of the constructor must be the output of -the @code{class} function called with the first argument being a -structure and the second argument being the class name. An example of -the call to this constructor function is then +Note that the return value of the constructor must be the output of the +@code{class} function. The first argument to the @code{class} function is a +structure and the second is the name of the class itself. An example of +calling the class constructor to create an instance is @example p = polynomial ([1, 0, 1]); @end example -Note that methods of a class can be documented. The help for the -constructor itself can be obtained with the constructor name, that is -for the polynomial constructor @code{help polynomial} will return the -help string. Also the help can be obtained by restricting the search -for the help to a particular class, for example @code{help -@@polynomial/polynomial}. This second method is the only means of -getting help for the overloaded methods and functions of the class. +Methods are defined by m-files in the class directory and can have embedded +documentation the same as any other m-file. The help for the constructor can +be obtained by using the constructor name alone, that is, for the polynomial +constructor @code{help polynomial} will return the help string. Help can be +restricted to a particular class by using the class directory name followed +by the method. For example, @code{help @@polynomial/polynomial} is another +way of displaying the help string for the polynomial constructor. This second +means is the only way to obtain help for the overloaded methods and functions +of the class. -The same is true for other Octave functions that take a function name -as an argument. For example @code{type @@polynomial/display} will -print the code of the display method of the polynomial class to the -screen, and @code{dbstop @@polynomial/display} will set a breakpoint -at the first executable line of the display method of the polynomial -class. +The same specification mechanism can be used wherever Octave expects a function +name. For example @code{type @@polynomial/display} will print the code of the +display method of the polynomial class to the screen, and +@code{dbstop @@polynomial/display} will set a breakpoint at the first +executable line of the display method of the polynomial class. -To check where a variable is a user class, the @code{isobject} and +To check whether a variable belongs to a user class, the @code{isobject} and @code{isa} functions can be used. For example: @example @@ -137,13 +136,13 @@ @DOCSTRING(isobject) @noindent -The available methods of a class can be displayed with the -@code{methods} function. +The available methods of a class can be displayed with the @code{methods} +function. @DOCSTRING(methods) @noindent -To inquire whether a particular method is available to a user class, the +To inquire whether a particular method exists for a user class, the @code{ismethod} function can be used. @DOCSTRING(ismethod) @@ -162,12 +161,12 @@ @node Manipulating Classes @section Manipulating Classes -There are a number of basic classes methods that can be defined to allow -the contents of the classes to be queried and set. The most basic of -these is the @code{display} method. The @code{display} method is used -by Octave when displaying a class on the screen, due to an expression -that is not terminated with a semicolon. If this method is not defined, -then Octave will printed nothing when displaying the contents of a class. +There are a number of basic class methods that can (and should) be defined to +allow the contents of the classes to be queried and set. The most basic of +these is the @code{display} method. The @code{display} method is used by +Octave when displaying a class on the screen, usually the result of an Octave +expression that does not end with a semicolon. If this method is not defined, +then Octave won't print anything when displaying the contents of a class. @DOCSTRING(display) @@ -179,46 +178,47 @@ @end example @noindent -Note that in the display method, it makes sense to start the method -with the line @code{fprintf ("%s =", inputname (1))} to be consistent -with the rest of Octave and print the variable name to be displayed -when displaying the class. +Note that in the display method it makes sense to start the method with the +line @code{printf ("%s =", inputname (1))} to be consistent with the rest of +Octave and print the variable name to be displayed when displaying a class +object. -To be consistent with the Octave graphic handle classes, a class -should also define the @code{get} and @code{set} methods. The -@code{get} method should accept one or two arguments, and given one -argument of the appropriate class it should return a structure with -all of the properties of the class. For example: +To be consistent with the Octave graphic handle classes, a class should also +define the @code{get} and @code{set} methods. The @code{get} method accepts +one or two arguments. The first argument is an object of the appropriate +class. If no other argument is given then the method should return a structure +with all the properties of the class. If a second argument is given it should +be a property name and the property specified should be retrieved. @example @EXAMPLEFILE(@polynomial/get.m) @end example @noindent -Similarly, the @code{set} method should taken as its first argument an -object to modify, and then take property/value pairs to be modified. +Similarly, the first argument to the @code{set} method should be an object and +any additional arguments should be property/value pairs. @example @EXAMPLEFILE(@polynomial/set.m) @end example @noindent -Note that as Octave does not implement pass by reference, than the -modified object is the return value of the @code{set} method and it -must be called like +Note that Octave does not implement pass by reference; Therefore, to modify an +object requires an assignment statement using the return value from the +@code{set} method. @example -p = set (p, "a", [1, 0, 0, 0, 1]); +p = set (p, "poly", [1, 0, 0, 0, 1]); @end example @noindent -Also the @code{set} method makes use of the @code{subsasgn} method of -the class, and this method must be defined. The @code{subsasgn} method -is discussed in the next section. +The @code{set} method makes use of the @code{subsasgn} method of the class, and +therefore this method must also be defined. The @code{subsasgn} method is +discussed more thoroughly in the next section (@pxref{Indexing Objects}). -Finally, user classes can be considered as a special type of a -structure, and so they can be saved to a file in the same manner as a -structure. For example: +Finally, user classes can be considered to be a special type of a structure, +and they can be saved to a file in the same manner as a structure. For +example: @example @group @@ -230,19 +230,18 @@ @end example @noindent -All of the file formats supported by @code{save} and @code{load} are -supported. In certain circumstances, a user class might either contain -a field that it makes no sense to save or a field that needs to be -initialized before it is saved. This can be done with the -@code{saveobj} method of the class +All of the file formats supported by @code{save} and @code{load} are supported. +In certain circumstances a user class might contain a field that it doesn't +make sense to save, or a field that needs to be initialized before it is saved. +This can be done with the @code{saveobj} method of the class. @DOCSTRING(saveobj) @noindent -@code{saveobj} is called just prior to saving the class to a -file. Likely, the @code{loadobj} method is called just after a class -is loaded from a file, and can be used to ensure that any removed -fields are reinserted into the user object. +@code{saveobj} is called just prior to saving the class to a file. Similarly, +the @code{loadobj} method is called just after a class is loaded from a file, +and can be used to ensure that any removed fields are reinserted into the user +object. @DOCSTRING(loadobj) @@ -257,21 +256,21 @@ @node Defining Indexing And Indexed Assignment @subsection Defining Indexing And Indexed Assignment -Objects can be indexed with parentheses, either like -@code{@var{a} (@var{idx})} or like @code{@var{a} @{@var{idx}@}}, or even -like @code{@var{a} (@var{idx}).@var{field}}. However, it is up to the user -to decide what this indexing actually means. In the case of our polynomial -class @code{@var{p} (@var{n})} might mean either the coefficient of the -@var{n}-th power of the polynomial, or it might be the evaluation of the +Objects can be indexed with parentheses or braces, either like +@code{@var{obj}(@var{idx})} or like @code{@var{obj}@{@var{idx}@}}, or even +like @code{@var{obj}(@var{idx}).@var{field}}. However, it is up to the +programmer to decide what this indexing actually means. In the case of the +polynomial class @code{@var{p}(@var{n})} might mean either the coefficient of +the @var{n}-th power of the polynomial, or it might be the evaluation of the polynomial at @var{n}. The meaning of this subscripted referencing is determined by the @code{subsref} method. @DOCSTRING(subsref) -For example we might decide that indexing with @qcode{"()"} evaluates the -polynomial and indexing with @qcode{"@{@}"} returns the @var{n}-th coefficient -(of @var{n}-th power). In this case the @code{subsref} method of our -polynomial class might look like +For example, this class uses the convention that indexing with @qcode{"()"} +evaluates the polynomial and indexing with @qcode{"@{@}"} returns the +@var{n}-th coefficient (of the @var{n}-th power). The code for the +@code{subsref} method of looks like @example @EXAMPLEFILE(@polynomial/subsref.m) @@ -289,10 +288,9 @@ responsibility of these methods to handle the rest of the chain (if needed), usually by forwarding it again to @code{subsref} or @code{subsasgn}. -If you wish to use the @code{end} keyword in subscripted expressions -of an object, then the user needs to define the @code{end} method for -the class. For example, the @code{end} method for our polynomial class might -look like +If you wish to use the @code{end} keyword in subscripted expressions of an +object, then the there must be an @code{end} method defined. For example, the +@code{end} method for the polynomial class might look like @example @group @@ -301,39 +299,36 @@ @end example @noindent -which is a fairly generic @code{end} method that has a behavior similar to -the @code{end} keyword for Octave Array classes. It can then be used as -follows: +which is a fairly generic @code{end} method that has a behavior similar to the +@code{end} keyword for Octave Array classes. It can then be used as follows: @example @group p = polynomial ([1,2,3,4]); -p(end-1) +p@{end-1@} @result{} 3 @end group @end example -Objects can also be used as the index in a subscripted expression themselves -and this is controlled with the @code{subsindex} function. +Objects can also be used themselves as the index in a subscripted expression +and this is controlled by the @code{subsindex} function. @DOCSTRING(subsindex) -Finally, objects can equally be used like ranges, using the @code{colon} -method +Finally, objects can be used like ranges by providing a @code{colon} method. @DOCSTRING(colon) @node Indexed Assignment Optimization @subsection Indexed Assignment Optimization -Octave's ubiquitous lazily-copied pass-by-value semantics implies -a problem for performance of user-defined subsasgn methods. Imagine -a call to subsasgn: +Octave's ubiquitous lazily-copied pass-by-value semantics implies a problem for +performance of user-defined subsasgn methods. Imagine a call to subsasgn: @example @group - ss = substruct ("()",@{1@}); - x = subsasgn (x, ss, 1); +ss = substruct ("()", @{1@}); +x = subsasgn (x, ss, 1); @end group @end example @@ -342,48 +337,47 @@ @example @group - function x = subsasgn (x, ss, val) - @dots{} - x.myfield (ss.subs@{1@}) = val; - endfunction +function x = subsasgn (x, ss, val) + @dots{} + x.myfield (ss.subs@{1@}) = val; +endfunction @end group @end example The problem is that on entry to the subsasgn method, @code{x} is still -referenced from the caller's scope, which means that the method will -first need to unshare (copy) @code{x} and @code{x.myfield} before performing -the assignment. Upon completing the call, unless an error occurs, -the result is immediately assigned to @code{x} in the caller's scope, -so that the previous value of @code{x.myfield} is forgotten. Hence, the -Octave language implies a copy of N elements (N being the size of -@code{x.myfield}), where modifying just a single element would actually -suffice, i.e., degrades a constant-time operation to linear-time one. -This may be a real problem for user classes that intrinsically store large -arrays. +referenced from the caller's scope, which means that the method will first need +to unshare (copy) @code{x} and @code{x.myfield} before performing the +assignment. Upon completing the call, unless an error occurs, the result is +immediately assigned to @code{x} in the caller's scope, so that the previous +value of @code{x.myfield} is forgotten. Hence, the Octave language implies a +copy of N elements (N being the size of @code{x.myfield}), where modifying just +a single element would actually suffice. In other words, a constant-time +operation is degraded to linear-time one. This may be a real problem for user +classes that intrinsically store large arrays. -To partially solve the problem, Octave uses a special optimization for -user-defined subsasgn methods coded as m-files. When the method -gets called as a result of the built-in assignment syntax (not direct subsasgn -call as shown above), i.e. +To partially solve the problem Octave uses a special optimization for +user-defined subsasgn methods coded as m-files. When the method gets called as +a result of the built-in assignment syntax (not a direct subsasgn call as shown +above), i.e., @example - x(1) = 1; +x(1) = 1; @end example -@b{AND} if the subsasgn method is declared with identical input and output argument, -like in the example above, then Octave will ignore the copy of @code{x} inside -the caller's scope; therefore, any changes made to @code{x} during the method -execution will directly affect the caller's copy as well. +@b{AND} if the subsasgn method is declared with identical input and output +arguments, as in the example above, then Octave will ignore the copy of +@code{x} inside the caller's scope; therefore, any changes made to @code{x} +during the method execution will directly affect the caller's copy as well. This allows, for instance, defining a polynomial class where modifying a single element takes constant time. It is important to understand the implications that this optimization brings. -Since no extra copy of @code{x} in the caller's scope will exist, it is +Since no extra copy of @code{x} will exist in the caller's scope, it is @emph{solely} the callee's responsibility to not leave @code{x} in an invalid -state if an error occurs throughout the execution. Also, if the method -partially changes @code{x} and then errors out, the changes @emph{will} affect -@code{x} in the caller's scope. Deleting or completely replacing @code{x} -inside subsasgn will not do anything, however, only indexed assignments matter. +state if an error occurs during the execution. Also, if the method partially +changes @code{x} and then errors out, the changes @emph{will} affect @code{x} +in the caller's scope. Deleting or completely replacing @code{x} inside +subsasgn will not do anything, however, only indexed assignments matter. Since this optimization may change the way code works (especially if badly written), a built-in variable @code{optimize_subsasgn_calls} is provided to @@ -392,9 +386,9 @@ @example @group - function y = subsasgn (x, ss, val) - @dots{} - endfunction +function y = subsasgn (x, ss, val) + @dots{} +endfunction @end group @end example @@ -410,10 +404,9 @@ @node Function Overloading @subsection Function Overloading -Any Octave function can be overloaded, and allows an object specific -version of this function to be called as needed. A pertinent example -for our polynomial class might be to overload the @code{polyval} function -like +Any Octave function can be overloaded, and this allows an object specific +version of a function to be called as needed. A pertinent example for the +polynomial class might be to overload the @code{polyval} function. @example @group @@ -422,7 +415,7 @@ @end example This function just hands off the work to the normal Octave @code{polyval} -function. Another interesting example for an overloaded function for our +function. Another interesting example of an overloaded function for the polynomial class is the @code{plot} function. @example @@ -432,14 +425,14 @@ @end example @noindent -which allows polynomials to be plotted in the domain near the region -of the roots of the polynomial. +which allows polynomials to be plotted in the domain near the region of the +roots of the polynomial. -Functions that are of particular interest to be overloaded are the class -conversion functions such as @code{double}. Overloading these functions -allows the @code{cast} function to work with the user class and can aid -in the use of methods of other classes with the user class. An example -@code{double} function for our polynomial class might look like. +Functions that are of particular interest for overloading are the class +conversion functions such as @code{double}. Overloading these functions allows +the @code{cast} function to work with a user class and can aid in the use of +methods of other classes with the user class. An example @code{double} +function for the polynomial class might look like @example @group @@ -601,7 +594,7 @@ @caption{Available overloaded operators and their corresponding class method} @end float -An example @code{mtimes} method for our polynomial class might look like +An example @code{mtimes} method for the polynomial class might look like @example @group @@ -612,18 +605,18 @@ @node Precedence of Objects @subsection Precedence of Objects -Many functions and operators take two or more arguments and so the -case can easily arise that these functions are called with objects of -different classes. It is therefore necessary to determine the precedence -of which method of which class to call when there are mixed objects given -to a function or operator. To do this the @code{superiorto} and -@code{inferiorto} functions can be used +Many functions and operators take two or more arguments and so the situation +can easily arise that these functions are called with objects of different +classes. It is therefore necessary to determine the precedence of which method +of which class to call when there are mixed objects given to a function or +operator. To do this the @code{superiorto} and @code{inferiorto} functions can +be used @DOCSTRING(superiorto) @DOCSTRING(inferiorto) -For example with our polynomial class consider the case +For example with the polynomial class consider the case @example 2 * polynomial ([1, 0, 1]); @@ -631,41 +624,40 @@ @noindent That mixes an object of the class @qcode{"double"} with an object of the class -@qcode{"polynomial"}. In this case we like to ensure that the return type of -the above is of the type @qcode{"polynomial"} and so we use the -@code{superiorto} function in the class constructor. In particular our -polynomial class constructor would be modified to be +@qcode{"polynomial"}. In this case the return type should be +@qcode{"polynomial"} and so the @code{superiorto} function is used in the class +constructor. In particular the polynomial class constructor would be modified +to @example @EXAMPLEFILE(@polynomial/polynomial_superiorto.m) @end example -Note that user classes always have higher precedence than built-in -Octave types. So in fact marking our polynomial class higher than the -@qcode{"double"} class is in fact not necessary. +Note that user classes always have higher precedence than built-in Octave +types. Thus, marking the polynomial class higher than the @qcode{"double"} +class is not actually necessary. -When faced with two objects that have the same precedence, Octave will use the -method of the object that appears first on the list of arguments. +When confronted with two objects with equal precedence, Octave will use the +method of the object that appears first in the list of arguments. @node Inheritance and Aggregation @section Inheritance and Aggregation -Using classes to build new classes is supported by octave through the -use of both inheritance and aggregation. +Using classes to build new classes is supported by octave through the use of +both inheritance and aggregation. -Class inheritance is provided by octave using the @code{class} -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. +Class inheritance is provided by octave using the @code{class} function in the +class constructor. As in the case of the polynomial class, the Octave +programmer will create a structure 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 structure. 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. -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. +This is most easily demonstrated by example. Suppose the programmer needs a +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. @example @group @@ -675,36 +667,36 @@ @end group @end example -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. +The equivalent class could be implemented in a class directory @@FIRfilter that +is on the Octave path. The constructor is a file @file{FIRfilter.m} in the +class directory. @example @EXAMPLEFILE(@FIRfilter/FIRfilter.m) @end example -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} function. The @code{class} 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. +As before, the leading comments provide documentation for the class +constructor. This constructor is very similar to the polynomial class +constructor, except that a polynomial object is passed as the third argument to +the @code{class} function, telling Octave that the FIRfilter class will be +derived from the polynomial class. The FIR filter does not have any data +fields, but it must provide a struct to the @code{class} function. The +@code{class} function will add an element named polynomial to the object +struct, so in this case a dummy element named polynomial is created as the +first line of the constructor. This dummy element will be overwritten by the +@code{class} function. -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. +Note that all of the sample code provide for the case in which no arguments are +supplied. This is important because Octave will call the constructor with no +arguments when loading objects from saved files in order to determine the +inheritance structure. -A class may be a child of more than one class (see the documentation -for the @code{class} 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. +A class may be a child of more than one class (see the documentation for the +@code{class} 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. -As before, we need a @code{display} method. A simple example might be +As before, a class requires a @code{display} method. A simple example might be @example @group @@ -712,12 +704,12 @@ @end group @end example -Note that we have used the polynomial field of the struct to display -the filter coefficients. +Note that the polynomial field of the struct is used to display the filter +coefficients. -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. +Once a constructor and display method exist, it is possible to create an +instance of the class. It is also possible to check the class type and examine +the underlying structure. @example @group @@ -737,11 +729,11 @@ @end group @end example -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} method may be used for both. +The only thing remaining to make this class usable is a method for processing +data. However, it is desirable to also have a way of changing the data stored +in the class. Since the fields in the underlying struct are private by +default, it is necessary to provide a mechanism to access the fields. The +@code{subsref} method may be used for both tasks. @example @EXAMPLEFILE(@FIRfilter/subsref.m) @@ -775,9 +767,9 @@ @end group @end example -In order to change the contents of the object, we need to define a -@code{subsasgn} method. For example, we may make the polynomial field -publicly writable. +In order to change the contents of the object a @code{subsasgn} method is +needed. For example, the following code makes the polynomial field publicly +writable @example @group @@ -785,25 +777,27 @@ @end group @end example -So that +@noindent +so that @example @group -octave:6> f = FIRfilter (); -octave:7> f.polynomial = polynomial ([1 2 3]); +octave:1> f = FIRfilter (); +octave:2> f.polynomial = polynomial ([1 2 3]) f.polynomial = 1 + 2 * X + 3 * X ^ 2 @end group @end example -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 +Defining the FIRfilter class as a child of the polynomial class implies that +a FIRfilter object may be used any place that a polynomial object may be used. +This is not a normal use of a filter. It may be a more sensible design +approach to use aggregation rather than inheritance. In this case, the +polynomial is simply a field in the class structure. A class constructor for +the aggregation case might be @example @EXAMPLEFILE(@FIRfilter/FIRfilter_aggregation.m) @end example -For our example, the remaining class methods remain unchanged. +For this example the other class methods remain unchanged. +