Subscripting: (optional)
- subsref: Used by y = x(i),
y = x{i}, y = x.i
- subsasgn: Used by x(i) = y,
x{i} = y, x.i = y
- subsindex: Used by y(x)
Arithmetic: (optional)
- plus, minus: Used by x+y, x-y
- uplus, uminus: Used by +x, -x
- mtimes, times: Used by x*y, x.*y
- mrdivide, rdivide: Used by x/y, x./y
- mldivide, ldivide: Used by x\y, x.\y
- mpower, power: Used by x^y, x.^y
- mtranspose, transpose: Used by x', x.'
- horzcat, vertcat: Used by [x y],
[x; y]
- colon: Used by x : y,
x : y : z
Relational: (optional)
- lt, le, ge, gt: Used by x < y, x <= y,
x >= y, x > y
- eq, ne: Used by x == y, x ~= y
Logical: (optional)
- and, or, not: Used by x & y, x | y, ~x
- double: Used by if(x), elseif(x),
while(x), for(x)
Build other functions: (optional)
- size(...): Used by whos.
- feval(...): Very handy.
- sqrt(...), tan(...), log(...), etc.
- plot(...), etc.
Object Updates
- Objects that change must be returned to the caller, since
they do not automatically persist the way "HandleGraphics"
items do. There is no way to recover a lost
object, unless it has been stored somewhere safely, such as
in the "UserData" of a long-lived graphical entity.
Class Privacy
- Internal subroutines are private to the parent M-file.
- Routines in a sub-folder named "private" are private
to the routines in the parent folder.
- Data inside an object are private. Direct access via
the "." operator is possible only from within the
methods of the same class. (Note: The struct(...)
function can retrieve private-data from the outside, but
cannot restore it.)
- Data inside the parent-class portion of an object are
not directly accessible from derived-class methods.
- Inside a class-method, the "()" operator refers to the
array-indices of the object(s) that triggered the
call, even though "()" may be overloaded for
public-use in subsref(...) or subsasgn(...).
To use the overloaded method from within, the subsref
and subsasgn methods must be called explicitly.
(Note that every Matlab entity is an array, even if an
array of just one element.)
- Inside a class-method, the "." operator refers to the
private-data of the object that triggered the call,
even though "." may be overloaded for public-use
in subsref(...) or subsasgn(...).
(This arrangement actually makes it possible to appear
to gain public-access to the private-data with ".",
but sensible users will avoid such schemes.)
- P-Code can be used to completely obscure the underlying
Matlab instructions of M-files, even for an entire
class. However, the P-Code does not incorporate the comments
of the originating M-files, so separate M-files must
be provided if "help" is to be made available. (Note that
P-Code files are not backwardly compatible between the three
versions of Matlab 5.)
Class Inheritance
- A class can be derived from one or more other classes,
making it possible to build upon existing classes without having
to re-write them. A POINT class, for example, might be used as
the basis for a LABELED_POINT class, which could invoke all the
methods of its parent, plus be able to manipulate an associated
label. Indeed, if there were also a LABEL class, then the
LABELED_POINT could be based upon two pre-existing classes.
A derived-class may need to call a parent-method before or
after using its own method of the same name. Matlab-5 does not
provide a direct function for such inheritance, but it is actually
easy to write one, because the "struct" function can get the
parent-object. The interesting challenge is to put the updated
parent-object back into the derived-object from whence it came.
For a specific class, test the class(...), whereas to check
for membership that includes any of the parent classes, use isa(...).
Thus, in the example above, a LABELED_POINT might be a member
of both the POINT and the LABEL classes, so far as
isa(...) is concerned.
Class Precedence
- Class-precedence ordinarily runs left-to-right in a calling-list,
unless it has been overruled by superiorto(...) and/or
inferiorto(...).
The regular Matlab data-types, such as "double" have the
lowest priority. The leftmost highest-priority "object" (in the
sense of the Matlab isobject(...) function) determines the
method to be called.
This means that users may need to inspect the class(...)
of each calling argument before deciding what to do.
For example, if x were a "double"
and y were a customized POINT object, then (x * y)
would cause the mtimes method of POINT to be called, as
mtimes(x, y).
The user would need to decide which argument was which in order to
handle the request, perhaps by "double-dispatching" it as (y * x).
Matlab-5 "Features"
- Non-indexed assignment "=" cannot be overloaded.
- Repeated "()", as in "x()()", is not allowed.
- Most other indexing combinations are permitted.
- help(...) cannot be overloaded.
- set(...) and get(...) cannot be overloaded.
- isa(...) returns TRUE for a derived-class.
- isequal(...) returns 0 when comparing NaN to NaN.
- assignin(...) cannot assign into the caller's caller.
- evalin(...) cannot evaluate in the caller's caller.
- inputname(...) cannot get the caller's inputnames.
- mfilename(...) cannot get the caller's caller's name.
- mfilename(...) returns 'classname/methodname' for methods.
- varargout must be preallocated as a
cell(1, nargout).
- All Matlab entities are arrays (often 1-by-1), including
doubles, chars, uint8s, structs, cells, and customized
objects. An array must contain only one kind of object.
That is, an array of "struct" contains structures all
with the same field-name sequence. An array of customized
objects contains objects all of the same class.
Base-classes and derived classes cannot be mixed in such
an array. Use cells or a container-class when mixing
disparate entities.
Good Citizenship
- Show help and/or a demo when no arguments are given.
- Use classname('demo') to show a demonstration.
- Use disp(...) to show a meaningful representation
of the object, not its internal details.
- Use eval('try', 'catch') and warning to exit gracefully.
- Use assignin('caller', 'ans', x) for silent answers.
- Use isequal(...) to test for exact-equality.
- Allow arguments passed as strings or cells.
- Return a value if requested.
Avoid If Possible
- Global variables.
- Multiple inheritance.
- superiorto(...) and inferiorto(...).
- "()" overloading when arrays of objects are expected.
- builtin(...).
- Logical operations that return non-logical answers.
- Sprinkling dandruff on the Matlab desktop.
- YELLING!!! at the user.
Object-Oriented Design
Object-oriented programming involves "programming to an interface",
yet the interface itself will most likely evolve, so the design
might be a continuing process. Any up-front design work will be
time well spent, especially in the early stages when the base-classes
are being conjured. A balance should be sought, wherein enough
classes of sufficient power and flexibility do emerge, but not too
many. You will know when you have gotten it right.
Good design and the workaday benefits of object-orientation
will be realized only through hands-on experience, including
looking at examples by other programmers. Please be assured
that there is no need to be religious about OO theory itself,
nor does everything need to be cast into the OO mold. Avoid
OO-mania, of course, but do keep in mind the fact that sensible
classes are worth all the effort it takes to build them.