# HG changeset patch # User Rik # Date 1452807022 28800 # Node ID a9ed4104ecfdc787d66ccac338f2acb76463433c # Parent f25c14056b7c30dba66300cbce47f471252a59da doc: Rewrite documentation for Object Oriented Programming. * octave.texi: Rename "Manipulating Classes" node to "Class Methods" * oop.txi: Rewrite signicant parts of Object Oriented Programming chapter. * examples/code/@FIRfilter/subsasgn.m, examples/code/@FIRfilter/subsref.m, examples/code/@polynomial/get.m, examples/code/@polynomial/subsasgn.m: Enclose property in error messages in double quotes ("%s"). * examples/code/@polynomial/subsref.m: Rename input object to 'p'. Rename variable "ind" to "idx". Enclose property in error messages in double quotes ("%s"). * ov-class.cc (Fsuperiorto, Finferiorto): Improve docstrings. * ov-usr-fcn.cc (Foptimize_subsasgn_calls): Improve docstring. * ov.cc (Fsubsref, Fsubsasgn): Improve docstrings. * display.m: Rewrite docstring. Rename input variable to "obj". Remove unused output variable from function declaration. * subsindex.m: Rename input variable to "obj". Rewrite examples in docstring. Add input validation and BIST tests to m-file. diff -r f25c14056b7c -r a9ed4104ecfd doc/interpreter/octave.texi --- a/doc/interpreter/octave.texi Thu Jan 14 14:00:32 2016 -0500 +++ b/doc/interpreter/octave.texi Thu Jan 14 13:30:22 2016 -0800 @@ -756,7 +756,7 @@ Object Oriented Programming * Creating a Class:: -* Manipulating Classes:: +* Class Methods:: * Indexing Objects:: * Overloading Objects:: * Inheritance and Aggregation:: diff -r f25c14056b7c -r a9ed4104ecfd doc/interpreter/oop.txi --- a/doc/interpreter/oop.txi Thu Jan 14 14:00:32 2016 -0500 +++ b/doc/interpreter/oop.txi Thu Jan 14 13:30:22 2016 -0800 @@ -24,11 +24,11 @@ @node Object Oriented Programming @chapter Object Oriented Programming -Octave includes the capability to create user-defined classes, including the +Octave has the ability 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. +internal properties so that they may 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 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. @@ -37,7 +37,7 @@ @menu * Creating a Class:: -* Manipulating Classes:: +* Class Methods:: * Indexing Objects:: * Overloading Objects:: * Inheritance and Aggregation:: @@ -47,8 +47,8 @@ @section Creating a Class 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 +through a custom class designed for polynomials. This class was chosen for +its simplicity which does not 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. @@ -80,14 +80,14 @@ a = [a0, a1, a2, @dots{}, an]; @end example -This is is a sufficient specification to begin writing the constructor for the +This 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. +directory that is the name of the class prepended with the @samp{@@} symbol. +For example, the polynomial class will have all of its methods defined in the +@file{@@polynomial} directory. 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}. +example the constructor resides in the file @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 @@ -112,7 +112,7 @@ 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. +of a 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 @@ -158,15 +158,16 @@ @end group @end example -@node Manipulating Classes -@section Manipulating Classes +@node Class Methods +@section Class Methods 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. +Octave whenever a class should be displayed on the screen. Usually this is the +result of an Octave expression that doesn't end with a semicolon. If this +method is not defined, then Octave won't print anything when displaying the +contents of a class which can be confusing. @DOCSTRING(display) @@ -179,16 +180,16 @@ @noindent 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. +line @w{@code{printf ("%s =", inputname (1))}} to be consistent with the rest +of Octave which prints the variable name to be displayed followed by the value. 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. +class. If no second argument is given then the method should return a +structure with all the properties of the class. If the optional second +argument is given it should be a property name and the specified property +should be retrieved. @example @EXAMPLEFILE(@polynomial/get.m) @@ -270,7 +271,7 @@ 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 +@code{subsref} method looks like @example @EXAMPLEFILE(@polynomial/subsref.m) @@ -289,7 +290,7 @@ 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 there must be an @code{end} method defined. For example, the +object, then there must be an @code{end} method defined. For example, the @code{end} method for the polynomial class might look like @example @@ -300,7 +301,8 @@ @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: +@code{end} keyword for Octave Array classes. An example using the polynomial +class is then @example @group @@ -323,7 +325,8 @@ @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: +performance of user-defined @code{subsasgn} methods. Imagine the following +call to @code{subsasgn} @example @group @@ -333,7 +336,7 @@ @end example @noindent -and the corresponding method looking like this: +where the corresponding method looking like this: @example @group @@ -344,7 +347,7 @@ @end group @end example -The problem is that on entry to the subsasgn method, @code{x} is still +The problem is that on entry to the @code{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 @@ -356,15 +359,10 @@ 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 a direct subsasgn call as shown -above), i.e., - -@example -x(1) = 1; -@end example - -@b{AND} if the subsasgn method is declared with identical input and output +user-defined @code{subsasgn} methods coded as m-files. When the method gets +called as a result of the built-in assignment syntax (not a direct +@code{subsasgn} call as shown above), i.e., @w{@code{x(1) = 1}}, @b{AND} if +the @code{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. @@ -381,8 +379,8 @@ Since this optimization may change the way code works (especially if badly written), a built-in variable @code{optimize_subsasgn_calls} is provided to -control it. It is on by default. Another option to avoid the effect is to -declare subsasgn methods with different output and input arguments, like this: +control it. It is on by default. Another way to avoid the optimization is to +declare subsasgn methods with different output and input arguments like this: @example @group @@ -404,7 +402,7 @@ @node Function Overloading @subsection Function Overloading -Any Octave function can be overloaded, and this allows an object specific +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. @@ -430,9 +428,10 @@ 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 +the @code{cast} function to work with a user class. It can also can aid in the +use of a class object with methods and functions from other classes since the +object can be transformed to the requisite input form for the new function. +An example @code{double} function for the polynomial class might look like @example @group @@ -605,10 +604,10 @@ @node Precedence of Objects @subsection Precedence of Objects -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 +Many functions and operators take two or more arguments and the situation can +easily arise where 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 +from 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 @@ -616,14 +615,14 @@ @DOCSTRING(inferiorto) -For example with the polynomial class consider the case +With the polynomial class, consider the case @example 2 * polynomial ([1, 0, 1]); @end example @noindent -That mixes an object of the class @qcode{"double"} with an object of the class +that mixes an object of the class @qcode{"double"} with an object of the class @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 @@ -633,31 +632,30 @@ @EXAMPLEFILE(@polynomial/polynomial_superiorto.m) @end example -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. +Note that user classes @emph{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 confronted with two objects with equal precedence, Octave will use the +When confronted with two objects of 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 +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 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. +the class, and then call the @code{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 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. +FIR filter, i.e., a filter with a numerator polynomial but a denominator of 1. +In traditional Octave programming this would be performed as follows. @example @group @@ -667,9 +665,9 @@ @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 @file{FIRfilter.m} in the -class directory. +The equivalent behavior can be implemented as a class @@FIRfilter. The +constructor for this class is the file @file{FIRfilter.m} in the class +directory @file{@@FIRfilter}. @example @EXAMPLEFILE(@FIRfilter/FIRfilter.m) @@ -678,23 +676,21 @@ 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. +the @code{class} function, telling Octave that the @w{FIRfilter} class will be +derived from the polynomial class. The FIR filter class itself does not have +any data fields, but it must provide a struct to the @code{class} function. +Given that the @@polynomial constructor will add an element named +@var{polynomial} to the object struct, the @@FIRfilter just initializes a +struct with a dummy field @var{polynomial} which will later be overwritten. -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 +Note that the sample code always provides for the case in which no arguments +are supplied. This is important because Octave will call a 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 (@pxref{XREFclass,,class}), 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, a class requires a @code{display} method. A simple example might be @@ -704,8 +700,8 @@ @end group @end example -Note that the polynomial field of the struct is used to display the filter -coefficients. +Note that the @w{FIRfilter}'s display method relies on the display method +from the polynomial class to actually display the filter coefficients. 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 @@ -714,26 +710,27 @@ @example @group octave:1> f = FIRfilter (polynomial ([1 1 1]/3)) -f.polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2 +f.polynomial = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2 octave:2> class (f) ans = FIRfilter -octave:3> isa (f,"FIRfilter") +octave:3> isa (f, "FIRfilter") ans = 1 -octave:4> isa (f,"polynomial") +octave:4> isa (f, "polynomial") ans = 1 octave:5> struct (f) ans = -@{ -polynomial = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2 -@} + + scalar structure containing the fields: + +polynomial = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2 @end group @end example 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. +data. But before that, it is usually desirable to also have a way of changing +the data stored in a 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) @@ -763,7 +760,7 @@ @group octave:1> f = FIRfilter (polynomial ([1 1 1]/3)); octave:2> f.polynomial -ans = 0.333333 + 0.333333 * X + 0.333333 * X ^ 2 +ans = 0.33333 + 0.33333 * X + 0.33333 * X ^ 2 @end group @end example @@ -788,10 +785,10 @@ @end group @end example -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 +Defining the @w{FIRfilter} class as a child of the polynomial class implies +that a @w{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 @@ -799,5 +796,6 @@ @EXAMPLEFILE(@FIRfilter/FIRfilter_aggregation.m) @end example -For this example the other class methods remain unchanged. +For this example only the constructor needs changing, and all other class +methods stay the same. diff -r f25c14056b7c -r a9ed4104ecfd examples/code/@FIRfilter/subsasgn.m --- a/examples/code/@FIRfilter/subsasgn.m Thu Jan 14 14:00:32 2016 -0500 +++ b/examples/code/@FIRfilter/subsasgn.m Thu Jan 14 13:30:22 2016 -0800 @@ -4,7 +4,7 @@ case "." fld = index.subs; if (! strcmp (fld, "polynomial")) - error ("@FIRfilter/subsasgn: invalid property '%s'", fld); + error ('@FIRfilter/subsasgn: invalid property "%s"', fld); endif fout = f; fout.polynomial = val; diff -r f25c14056b7c -r a9ed4104ecfd examples/code/@FIRfilter/subsref.m --- a/examples/code/@FIRfilter/subsref.m Thu Jan 14 14:00:32 2016 -0500 +++ b/examples/code/@FIRfilter/subsref.m Thu Jan 14 13:30:22 2016 -0800 @@ -9,7 +9,7 @@ case "." fld = x.subs; if (! strcmp (fld, "polynomial")) - error ("@FIRfilter/subsref: invalid property '%s'", fld); + error ('@FIRfilter/subsref: invalid property "%s"', fld); endif r = f.polynomial; diff -r f25c14056b7c -r a9ed4104ecfd examples/code/@polynomial/get.m --- a/examples/code/@polynomial/get.m Thu Jan 14 14:00:32 2016 -0500 +++ b/examples/code/@polynomial/get.m Thu Jan 14 13:30:22 2016 -0800 @@ -15,7 +15,7 @@ case "poly" val = p.poly; otherwise - error ("@polynomial/get: invalid PROPERTY '%s'", prop); + error ('@polynomial/get: invalid PROPERTY "%s"', prop); endswitch endif diff -r f25c14056b7c -r a9ed4104ecfd examples/code/@polynomial/subsasgn.m --- a/examples/code/@polynomial/subsasgn.m Thu Jan 14 14:00:32 2016 -0500 +++ b/examples/code/@polynomial/subsasgn.m Thu Jan 14 13:30:22 2016 -0800 @@ -23,7 +23,7 @@ case "." fld = s(1).subs; if (! strcmp (fld, "poly")) - error ("@polynomial/subsasgn: invalid property '%s'", fld); + error ('@polynomial/subsasgn: invalid property "%s"', fld); endif if (numel (s) == 1) p.poly = val; diff -r f25c14056b7c -r a9ed4104ecfd examples/code/@polynomial/subsref.m --- a/examples/code/@polynomial/subsref.m Thu Jan 14 14:00:32 2016 -0500 +++ b/examples/code/@polynomial/subsref.m Thu Jan 14 13:30:22 2016 -0800 @@ -1,4 +1,4 @@ -function r = subsref (a, s) +function r = subsref (p, s) if (isempty (s)) error ("@polynomial/subsref: missing index"); @@ -7,30 +7,30 @@ switch (s(1).type) case "()" - ind = s(1).subs; - if (numel (ind) != 1) + idx = s(1).subs; + if (numel (idx) != 1) error ("@polynomial/subsref: need exactly one index"); endif - r = polyval (fliplr (a.poly), ind{1}); + r = polyval (fliplr (p.poly), idx{1}); case "{}" - ind = s(1).subs; - if (numel (ind) != 1) + idx = s(1).subs; + if (numel (idx) != 1) error ("@polynomial/subsref: need exactly one index"); endif - if (isnumeric (ind{1})) - r = a.poly(ind{1}+1); + if (isnumeric (idx{1})) + r = p.poly(idx{1}+1); else - r = a.poly(ind{1}); + r = p.poly(idx{1}); endif case "." fld = s.subs; if (! strcmp (fld, "poly")) - error ("@polynomial/subsref: invalid property '%s'", fld); + error ('@polynomial/subsref: invalid property "%s"', fld); endif - r = a.poly; + r = p.poly; otherwise error ("@polynomial/subsref: invalid subscript type"); diff -r f25c14056b7c -r a9ed4104ecfd libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Thu Jan 14 14:00:32 2016 -0500 +++ b/libinterp/octave-value/ov-class.cc Thu Jan 14 13:30:22 2016 -0800 @@ -1993,11 +1993,11 @@ DEFUN (superiorto, args, , "-*- texinfo -*-\n\ @deftypefn {} {} superiorto (@var{class_name}, @dots{})\n\ -When called from a class constructor, mark the object currently\n\ -constructed as having a higher precedence than @var{class_name}.\n\ +When called from a class constructor, mark the object currently constructed\n\ +as having a higher precedence than @var{class_name}.\n\ \n\ -More that one such class can be specified in a single call.\n\ -This function may only be called from a class constructor.\n\ +More that one such class can be specified in a single call. This function\n\ +may @emph{only} be called from a class constructor.\n\ @seealso{inferiorto}\n\ @end deftypefn") { @@ -2026,11 +2026,11 @@ DEFUN (inferiorto, args, , "-*- texinfo -*-\n\ @deftypefn {} {} inferiorto (@var{class_name}, @dots{})\n\ -When called from a class constructor, mark the object currently\n\ -constructed as having a lower precedence than @var{class_name}.\n\ +When called from a class constructor, mark the object currently constructed\n\ +as having a lower precedence than @var{class_name}.\n\ \n\ -More that one such class can be specified in a single call.\n\ -This function may only be called from a class constructor.\n\ +More that one such class can be specified in a single call. This function\n\ +may @emph{only} be called from a class constructor.\n\ @seealso{superiorto}\n\ @end deftypefn") { diff -r f25c14056b7c -r a9ed4104ecfd libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Thu Jan 14 14:00:32 2016 -0500 +++ b/libinterp/octave-value/ov-usr-fcn.cc Thu Jan 14 13:30:22 2016 -0800 @@ -987,14 +987,16 @@ @deftypefn {} {@var{val} =} optimize_subsasgn_calls ()\n\ @deftypefnx {} {@var{old_val} =} optimize_subsasgn_calls (@var{new_val})\n\ @deftypefnx {} {} optimize_subsasgn_calls (@var{new_val}, \"local\")\n\ -Query or set the internal flag for subsasgn method call optimizations.\n\ +Query or set the internal flag for @code{subsasgn} method call\n\ +optimizations.\n\ \n\ If true, Octave will attempt to eliminate the redundant copying when calling\n\ -the subsasgn method of a user-defined class.\n\ +the @code{subsasgn} method of a user-defined class.\n\ \n\ When called from inside a function with the @qcode{\"local\"} option, the\n\ variable is changed locally for the function and any subroutines it calls.\n\ The original variable value is restored when exiting the function.\n\ +@seealso{subsasgn}\n\ @end deftypefn") { return SET_INTERNAL_VARIABLE (optimize_subsasgn_calls); diff -r f25c14056b7c -r a9ed4104ecfd libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Thu Jan 14 14:00:32 2016 -0500 +++ b/libinterp/octave-value/ov.cc Thu Jan 14 13:30:22 2016 -0800 @@ -2981,13 +2981,13 @@ DEFUN (subsref, args, nargout, "-*- texinfo -*-\n\ @deftypefn {} {} subsref (@var{val}, @var{idx})\n\ -Perform the subscripted element selection operation according to the\n\ -subscript specified by @var{idx}.\n\ +Perform the subscripted element selection operation on @var{val} according\n\ +to the subscript specified by @var{idx}.\n\ \n\ -The subscript @var{idx} is expected to be a structure array with fields\n\ -@samp{type} and @samp{subs}. Valid values for @samp{type} are\n\ -@samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}. The @samp{subs} field may\n\ -be either @samp{\":\"} or a cell array of index values.\n\ +The subscript @var{idx} must be a structure array with fields @samp{type}\n\ +and @samp{subs}. Valid values for @samp{type} are @qcode{\"()\"},\n\ +@qcode{\"@{@}\"}, and @qcode{\".\"}. The @samp{subs} field may be either\n\ +@qcode{\":\"} or a cell array of index values.\n\ \n\ The following example shows how to extract the first two columns of a matrix\n\ \n\ @@ -3007,7 +3007,7 @@ @end example\n\ \n\ @noindent\n\ -Note that this is the same as writing @code{val(:,1:2)}.\n\ +Note that this is the same as writing @code{val(:, 1:2)}.\n\ \n\ If @var{idx} is an empty structure array with fields @samp{type} and\n\ @samp{subs}, return @var{val}.\n\ @@ -3040,10 +3040,10 @@ Perform the subscripted assignment operation according to the subscript\n\ specified by @var{idx}.\n\ \n\ -The subscript @var{idx} is expected to be a structure array with fields\n\ -@samp{type} and @samp{subs}. Valid values for @samp{type} are\n\ -@samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}. The @samp{subs} field may\n\ -be either @samp{\":\"} or a cell array of index values.\n\ +The subscript @var{idx} must be a structure array with fields @samp{type}\n\ +and @samp{subs}. Valid values for @samp{type} are @qcode{\"()\"},\n\ +@qcode{\"@{@}\"}, and @qcode{\".\"}. The @samp{subs} field may be either\n\ +@qcode{\":\"} or a cell array of index values.\n\ \n\ The following example shows how to set the two first columns of a 3-by-3\n\ matrix to zero.\n\ @@ -3060,11 +3060,11 @@ @end group\n\ @end example\n\ \n\ -Note that this is the same as writing @code{val(:,1:2) = 0}.\n\ +Note that this is the same as writing @code{val(:, 1:2) = 0}.\n\ \n\ If @var{idx} is an empty structure array with fields @samp{type} and\n\ @samp{subs}, return @var{rhs}.\n\ -@seealso{subsref, substruct}\n\ +@seealso{subsref, substruct, optimize_subsasgn_calls}\n\ @end deftypefn") { if (args.length () != 3) diff -r f25c14056b7c -r a9ed4104ecfd scripts/general/display.m --- a/scripts/general/display.m Thu Jan 14 14:00:32 2016 -0500 +++ b/scripts/general/display.m Thu Jan 14 13:30:22 2016 -0800 @@ -17,36 +17,42 @@ ## . ## -*- texinfo -*- -## @deftypefn {} {} display (@var{a}) -## Display the contents of an object. +## @deftypefn {} {} display (@var{obj}) +## Display the contents of the object @var{obj}. ## -## If @var{a} is an object of the class @qcode{"myclass"}, then @code{display} -## is called in a case like +## The Octave interpreter calls the @code{display} function whenever it needs +## to present a class on-screen. Typically, this would be a statement which +## does not end in a semicolon to suppress output. For example, ## ## @example -## myclass (@dots{}) +## myobj = myclass (@dots{}) ## @end example ## -## @noindent -## where Octave is required to display the contents of a variable of the -## type @qcode{"myclass"}. +## User-defined classes should overload the @code{display} method so that +## something useful is printed for a class object. Otherwise, Octave will +## report only that the object is an instance of its class. ## +## @example +## myobj = myclass (@dots{}) +## @result{} myobj = +## @end example +## ## @seealso{class, subsref, subsasgn} ## @end deftypefn -function idx = display (a) +function display (obj) if (nargin != 1) print_usage (); endif - ## Only reason we got here is that there was no overloaded display() - ## function for object a. This may mean it is a built-in. - str = disp (a); + ## Only reason we got here is that there was no overloaded display function. + ## This may mean it is a built-in class. + str = disp (obj); if (isempty (strfind (str, ". ## -*- texinfo -*- -## @deftypefn {} {@var{idx} =} subsindex (@var{a}) +## @deftypefn {} {@var{idx} =} subsindex (@var{obj}) ## Convert an object to an index vector. ## -## When @var{a} is a class object defined with a class constructor, then +## When @var{obj} is a class object defined with a class constructor, then ## @code{subsindex} is the overloading method that allows the conversion of ## this class object to a valid indexing vector. It is important to note that ## @code{subsindex} must return a zero-based real integer vector of the class -## @qcode{"double"}. For example, if the class constructor +## @qcode{"double"}. For example, if the class constructor were ## ## @example ## @group -## function b = myclass (a) -## b = class (struct ("a", a), "myclass"); +## function obj = myclass (a) +## obj = class (struct ("a", a), "myclass"); ## endfunction ## @end group ## @end example @@ -39,14 +39,14 @@ ## ## @example ## @group -## function idx = subsindex (a) -## idx = double (a.a) - 1.0; +## function idx = subsindex (obj) +## idx = double (obj.a) - 1.0; ## endfunction ## @end group ## @end example ## ## @noindent -## can then be used as follows +## could be used as follows ## ## @example ## @group @@ -60,7 +60,21 @@ ## @seealso{class, subsref, subsasgn} ## @end deftypefn -function idx = subsindex (a) - error ("subsindex: not defined for class \"%s\"", class (a)); +function idx = subsindex (obj) + + if (nargin != 1) + print_usage (); + endif + + ## Only way to get here is if subsindex has not been overloaded by a class. + error ('subsindex: not defined for class "%s"', class (obj)); + endfunction + +%!error subsindex (1) + +## Test input validation +%!error subsindex () +%!error subsindex (1, 2) +