diff doc/interpreter/oop.txi @ 8223:0c91b9a17dcf

Commit missing files from previous change
author David Bateman <dbateman@free.fr>
date Thu, 16 Oct 2008 09:20:58 +0100
parents
children 7eedf503ba1c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/interpreter/oop.txi	Thu Oct 16 09:20:58 2008 +0100
@@ -0,0 +1,474 @@
+@c Copyright (C) 2008 David Bateman
+@c
+@c This file is part of Octave.
+@c
+@c Octave is free software; you can redistribute it and/or modify it
+@c under the terms of the GNU General Public License as published by the
+@c Free Software Foundation; either version 3 of the License, or (at
+@c your option) any later version.
+@c 
+@c Octave is distributed in the hope that it will be useful, but WITHOUT
+@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+@c FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+@c for more details.
+@c 
+@c You should have received a copy of the GNU General Public License
+@c along with Octave; see the file COPYING.  If not, see
+@c <http://www.gnu.org/licenses/>.
+
+@c FIXME
+@c For now can't include "@" character in the path name, and so name
+@c the example directory without the "@"!!
+
+@macro classfile{class, file}
+@example
+@group
+@verbatiminclude @value{abs_top_srcdir}/examples/\class\/\file\
+@end group
+@end example
+@end macro
+
+@macro polynomialfile{file}
+@classfile{polynomial,\file\}
+@end macro
+
+@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 can not be altered accidentally and can be set up 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.
+
+@menu
+* Creating a Class::
+* Manipulating Classes::
+* Indexing Objects::
+* Overloading Objects::
+@end menu
+
+@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.
+
+The polynomial class is used to represent polynomials of the form
+
+@example
+@iftex
+@tex
+$a_0 + a_1 x + a_2 x^2 + \ldots a_n x^n$
+@end tex
+@end iftex
+@ifnottex
+a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
+@end ifnottex
+@end example
+
+@noindent
+where
+@iftex
+@tex
+$a_0$, $a_1$, etc are elements of $\Re$.
+@end tex
+@end iftex
+@ifnottex
+a0, a1, etc are real scalars.
+@end ifnottex
+Thus the polynomial can be represented by a vector
+
+@example
+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.
+
+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
+
+@polynomialfile{polynomial.m}
+
+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
+
+@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.
+
+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.
+
+To check where a variable is a user class, the @code{isobject} and
+@code{isa} functions can be used. for example
+
+@example
+@group
+p = polynomial ([1, 0, 1]);
+isobject (p)
+@result{} 1
+isa (p, "polynomial")
+@result{} 1
+@end group
+@end example
+
+@DOCSTRING(isobject)
+
+@noindent
+The available methods of a class can be displayed with the
+@code{methods} function.
+
+@DOCSTRING(methods)
+
+@noindent
+To enquiry whether a particular method is available to a user class, the
+@code{ismethod} function can be used.
+
+@DOCSTRING(ismethod)
+
+@noindent
+For example
+
+@example
+@group
+p = polynomial ([1, 0, 1]);
+ismethod (p, "roots")
+@result{} 1
+@end group
+@end example
+
+@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.
+
+@DOCSTRING(display)
+
+@noindent
+An example of a display method for the polynomial class might be
+
+@polynomialfile{display.m}
+
+@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. 
+
+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
+
+@polynomialfile{get.m}
+
+@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. 
+
+@polynomialfile{set.m}
+
+@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
+
+@example
+p = set (p, "a", [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.
+
+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
+
+@example
+@group
+p = polynomial ([1, 0, 1]);
+save userclass.mat p
+clear p
+load userclass.mat
+@end group
+@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
+
+@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.
+
+@DOCSTRING(loadobj)
+
+@node Indexing Objects
+@section Indexing Objects
+
+Objects in can be indexed with parenthesises, 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 
+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 "()" evaluates the
+polynomial and indexing with "{}" returns the @var{n}-th coefficient.
+In this case the @code{subsref} method of our polynomial class might look like
+
+@polynomialfile{subsref.m}
+
+The equivalent functionality for subscripted asignments uses the 
+@code{subsasgn} method.
+
+@DOCSTRING(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.
+
+@DOCSTRING(end)
+
+For example the @code{end} method for our polynomial class might look like
+
+@polynomialfile{end.m}
+
+@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 for
+example like
+
+@example
+@group
+p = polynomial([1,2,3,4]);
+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.
+
+@DOCSTRING(subsindex)
+
+Finally, objects can equally be used like ranges, using the @code{colon}
+method
+
+@DOCSTRING(colon)
+
+@node Overloading Objects
+@section Overloading Objects
+
+@menu
+* Function Overloading::
+* Operator Overloading::
+* Precedence of Objects::
+@end menu
+
+@node Function Overloading
+@subsection Function Overloading
+
+Any Octave function can be overloaded, and allows a 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
+
+@polynomialfile{polyval.m}
+
+This function just hands off the work to the normal Octave @code{polyval}
+function. Another interesting example for an overloaded function for our
+polynomial class is the @code{plot} function.
+
+@polynomialfile{plot.m}
+
+@noindent
+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.
+
+@polynomialfile{double.m}
+
+@node Operator Overloading
+@subsection Operator Overloading
+
+@float Table,tab:overload_ops
+@iftex
+@tex
+\vskip 6pt
+{\hbox to \hsize {\hfill\vbox{\offinterlineskip \tabskip=0pt 
+\halign{
+\vrule height2.0ex depth1.ex width 0.6pt #\tabskip=0.3em &
+# \hfil & \vrule # & # \hfil & \vrule # & # \hfil & # \vrule 
+width 0.6pt \tabskip=0pt\cr
+\noalign{\hrule height 0.6pt}
+& Operation && Method && Description &\cr
+\noalign{\hrule}
+& $a + b$ && plus (a, b) && Binary addition operator&\cr
+& $a - b$ && plus (a, b) && Binary subtraction operator&\cr
+& $+ a$ && uplus (a) && Unary addition operator&\cr
+& $- a$ && uminus (a) && Unary subtraction operator&\cr
+& $a .* b$ && times (a, b) && Element-wise multiplication operator&\cr
+& $a * b$ && mtimes (a, b) && Matrix multiplication operator&\cr
+& $a ./ b$ && rdivide (a, b) && Element-wise right division operator&\cr
+& $a / b$ && mrdivide (a, b) && Matrix right division operator&\cr
+& $a .\backslash b$ && ldivide (a, b) && Element-wise left division operator&\cr
+& $a \backslash b$ && mldivide (a, b) && Matrix left division operator&\cr
+& $a .\hat b$ && power (a, b) && Element-wise power operator&\cr
+& $a \hat b$ && mpower (a, b) && Matrix power operator&\cr
+& $a < b$ && lt (a, b) && Less than operator&\cr
+& $a <= b$ && le (a, b) && Less than or equal to operator&\cr
+& $a > b$ && gt (a, b) && Greater than operator&\cr
+& $a >= b$ && ge (a, b) && Greater than or equal to operator&\cr
+& $a == b$ && eq (a, b) && Equal to operator&\cr
+& $a != b$ && ne (a, b) && Not equal to operator&\cr
+& $a \& b$ && and (a, b) && Logical and operator&\cr
+& $a | b$ && or (a, b) && Logical or operator&\cr
+& $! b$ && not (a) && Logical not operator&\cr
+& $a'$ && ctranspose (a) && Complex conjugate transpose operator &\cr
+& $a.'$ && transpose (a) && Transpose operator &\cr
+& $a : b$ && colon (a, b) && Two element range operator &\cr
+& $a : b : c$ && colon (a, b, c) && Three element range operator &\cr
+& $[a, b]$ && horzcat (a, b) && Horizontal concatenation opertaor &\cr
+& $[a; b]$ && vertcat (a, b) && Vertical concatenation opertaor &\cr
+& $a(s_1, \ldots, s_n)$ && subsref (a, s) && Subscripted reference &\cr
+& $a(s_1, \ldots, s_n) = b$ && subsasgn (a, s, b) && Subscripted assignment &\cr
+& $b (a)$ && subsindex (a) && Convert to zero-based index &\cr
+& {\it display} && display (a) && Commandline display function &\cr
+\noalign{\hrule height 0.6pt}
+}}\hfill}}
+@end tex
+@end iftex
+@ifnottex
+@multitable @columnfractions .1 .20 .20 .40 .1
+@item @tab Operation @tab Method @tab Description @tab
+@item @tab a + b @tab plus (a, b) @tab Binary addition @tab
+@item @tab a - b$ @tab plus (a, b) @tab Binary subtraction operator @tab
+@item @tab + a$ @tab uplus (a) @tab Unary addition operator @tab
+@item @tab - a$ @tab uminus (a) @tab Unary subtraction operator @tab
+@item @tab a .* b$ @tab times (a, b) @tab Element-wise multiplication operator @tab
+@item @tab a * b$ @tab mtimes (a, b) @tab Matirx multiplication operator @tab
+@item @tab a ./ b$ @tab rdivide (a, b) @tab Element-wise right division operator @tab
+@item @tab a / b$ @tab mrdivide (a, b) @tab Matrix right division operator @tab
+@item @tab a .\ b$ @tab ldivide (a, b) @tab Element-wise left division operator @tab
+@item @tab a \ b$ @tab mldivide (a, b) @tab Matrix left division operator @tab
+@item @tab a .^ b$ @tab ldivide (a, b) @tab Element-wise power operator @tab
+@item @tab a ^ b$ @tab mldivide (a, b) @tab Matrix power operator @tab
+@item @tab a < b$ @tab lt (a, b) @tab Less than operator @tab
+@item @tab a <= b$ @tab le (a, b) @tab Less than or equal to operator @tab
+@item @tab a > b$ @tab gt (a, b) @tab Greater than operator @tab
+@item @tab a >= b$ @tab ge (a, b) @tab Greater than or equal to operator @tab
+@item @tab a == b$ @tab eq (a, b) @tab Equal to operator @tab
+@item @tab a != b$ @tab ne (a, b) @tab Not equal to operator @tab
+@item @tab a \& b$ @tab and (a, b) @tab Logical and operator @tab
+@item @tab a | b$ @tab or (a, b) @tab Logical or operator @tab
+@item @tab ! b$ @tab not (a) @tab Logical not operator @tab
+@item @tab a'$ @tab ctranspose (a) @tab Complex conjugate transpose operator @tab
+@item @tab a.'$ @tab transpose (a) @tab Transpose operator @tab
+@item @tab a : b$ @tab colon (a, b) @tab Two element range operator @tab
+@item @tab a : b : c$ @tab colon (a, b, c) @tab Three element range operator @tab
+@item @tab [a, b]$ @tab horzcat (a, b) @tab Horizontal concatenation opertaor @tab
+@item @tab [a; b]$ @tab vertcat (a, b) @tab Vertical concatenation opertaor @tab
+@item @tab a(s_1, \ldots, s_n)$ @tab subsref (a, s) @tab Subscripted reference @tab
+@item @tab a(s_1, \ldots, s_n) = b$ @tab subsasgn (a, s, b) @tab Subscripted assignment @tab
+@item @tab b (a)$ @tab subsindex (a) @tab Convert to zero-based index @tab
+@item @tab  @dfn{display} @tab display (a) @tab Commandline display function @tab
+@end multitable
+@end ifnottex
+@caption{Available overloaded operators and their corresponding class method}
+@end float
+
+An example @code{mtimes} method for our polynomial class might look like
+
+@polynomialfile{mtimes.m}
+
+@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
+
+@DOCSTRING(superiorto)
+
+@DOCSTRING(inferiorto)
+
+For example with our polynomial class consider the case
+
+@example
+2 * polynomial ([1, 0, 1]);
+@end example
+
+@noindent
+That mixes an object of the class "double" with an object of the class
+"polynomial". In this case we like to ensure that the return type of
+the above is of the type "polynomial" and so we use the
+@code{superiorto} function in the class constructor. In particular our
+polynomial class constructor would be modified to be
+
+@polynomialfile{polynomial_superiorto.m}
+
+Note that user classes always have higher precedence than built-in
+Octave types. So in fact marking our polynomial class higher than the 
+"double" class is in fact not necessary.
+
+