UDD Properties

Donn Shull continues his series of articles on Matlab’s undocumented UDD mechanism. Today, Donn explains how to use and customize UDD properties.

Properties meta-data

The UDD system is a class system. UDD packages, classes, events, and properties are all classes. In this section we will take a closer look at property classes.

As we have already shown, properties are added to a UDD class by adding schema.prop calls to the schema.m class definition file. What this really means is that each property of a UDD class is itself a class object (schema.prop) with its own properties and methods. The methods of schema.prop are loadobj() and saveobj(), which are used to serialize objects of this class (i.e., storing them in a file or sending them elsewhere).

It is schema.prop‘s properties (so-called meta-properties) that interest us most:

PropertyData TypeDescription
AccessFlagsMatlab structureControls which objects can access (read/modify) the property
CaseSensitiveon/offDetermines if the exact case is required to access the property (i.e., can we use ‘casesensitive’ instead of ‘CaseSensitive’)
DataTypestringThe underlying object’s property data type, set by the constructor
DescriptionstringThis can hold a description of the property (normally empty)
FactoryValueAs specified by DataTypeThis is used to provide an initial or default property value
GetFunctionFunction handleA function handle that is called whenever the property value is read
NamestringThe name of the property, also set by the constructor
SetFunctionFunction handleA function handle that is called whenever the properties value is changed
Visibleon/offDetermines if a property will be displayed by the get method for a UDD object

We can manipulate the values of these meta-properties to control various aspects of our property:

% Create instance of simple.object
>> a = simple.object('a');
 
% Find the Value property and list its meta-properties
% We can manipulate these meta-properties within limits
>> a.findprop('Value').get
            Name: 'Value'
     Description: ''
        DataType: 'single'
    FactoryValue: 7.3891
     AccessFlags: [1x1 struct]
         Visible: 'on'
     GetFunction: []
     SetFunction: []
 
>> prop.Visible = 'off';  % i.e. hidden property (see below)
>> prop.AccessFlags.PublicSet = 'off';   % i.e. read-only
>> prop.AccessFlags.PublicGet = 'on';
 
% Find the DataType meta-property of the Value property
% This meta-property and all other schema.prop base class properties are fixed
>> a.findprop('Value').findprop('DataType').get
            Name: 'DataType'
     Description: ''
        DataType: 'string'
    FactoryValue: ''
           ...

Adding properties to existing objects in run-time

schema.prop is a very useful tool – it can be used to add new properties to existing object handles, even after these objects have been created. For example, let’s add a new property (MyFavoriteBlog) to a standard figure handle:

>> p=schema.prop(handle(gcf), 'MyFavoriteBlog','string')
p =
	schema.prop
 
>> set(gcf,'MyFavoriteBlog','UndocumentedMatlab.com')
 
>> get(gcf,'MyFavoriteBlog')
ans =
UndocumentedMatlab.com

Using this simple mechanism, we can add meaningful typed user data to any handle object. A similar functionality can be achieved via the setappdata/getappdata functions. However, the property-based approach above is much “cleaner” and more powerful, since we have built-in type checks, property-change event listeners and other useful goodies.

Property data types

In the article on creating UDD objects we saw that the Name and DataType meta-properties are set by the schema.prop constructor. Name must be a valid Matlab variable name (see isvarname).

DataType is more interesting: There are two equivalent universal data types, 'mxArray', and 'MATLAB array'. With either of these two data types a property can be set to a any Matlab type. If we use a more specific data type (e.g., ‘string’, ‘double’ or ‘handle’), Matlab automatically ensures the type validity whenever the property value is modified. In our simple.object we use ‘double’ and ‘string’. You can experiment with these and see that the Value property will only allow scalar numeric values and the Name property will only allow character values:

>> set(obj, 'Value', 'abcd')
??? Parameter must be scalar.
 
>> obj.Value='abcd'
??? Parameter must be scalar.
 
>> obj.Name=123
??? Parameter must be a string.

The following table lists the basic UDD data types:

CategoryData Type
UniversalMATLAB array, mxArray
Numeric Scalarsbool, byte, short, int, long, float, double
Numeric VectorsNints, NReals
Specialized Numericcolor, point, real point, real point3, rect, real rect
Enumerationon/off
Stringschar, string, NStrings, string vector
Handlehandle, handle vector, MATLAB callback, GetFunction, SetFunction
JavaAny java class recognized by Matlab

User-defined data types

While this is an extensive list, there are some obvious types missing. For example there are no unsigned integer types. To handle this UDD provides two facilities for creating your own data types. One is the schema.EnumType. As you can see, Matlab has had a form of enumerations for a really long time not just the last few releases. The other facility is schema.UserType.

With these two classes you can create any specialized data type you need. One word of caution: once you have created a new UDD data type it exists for the duration of that Matlab session. There is no equivalent of the clear classes mechanism for removing a data type. In addition once a new data type has been defined it cannot be redefined until Matlab is restarted.

Let’s use a problem discussed in the CSSM forum as example. The essence of the problem is the need to flag a graphic line object as either editable or not. The proposed proposed is to add a new Editable property to an existing line handle. We will use schema.EnumType to create a new type named 'yes/no' so that the new property could accept only ‘yes’ and ‘no’ values:

function tline = taggedLine(varargin)
%TAGGEDLINE create a line with Editable property
%
%   TLINE = TAGGEDLINE(VARARGIN) create a new handle graphics line
%   and add 'Ediatable' property to line. Default property value is 'yes'.
%
%   INPUTS:
%       VARARGIN  : property value pairs to pass to line
%
%   OUTPUTS:
%       TLINE     : hg line object with Editable property
 
    % If undefined define yes/no datatype</font>
    if isempty(findtype('yes/no'))
        schema.EnumType('yes/no', {'yes', 'no'});
    end
    tline = line(varargin{:});
    schema.prop(tline, 'Editable', 'yes/no');
end

It is necessary to test for the existence of a type before defining it, since trying to redefine a type will generate an error.

We can use this new taggedLine() function to create new line objects with the additional Editable property. Instead of adding a new property to the line class we could have defined a new class as a subclass of line:

function schema()
%SCHEMA  hg package definition function
    schema.package('hg');
end

We create our class definition as a subclass of the handle graphics line class:

function schema()
%SCHEMA  hg.taggedline class definition function
    % package definition
    superPackage = findpackage('hg');
    pkg = findpackage('hg');
 
    % class definition
    c = schema.class(pkg, 'taggedline', findclass(superPackage, 'line'));
 
    if isempty(findtype('yes/no'))
        schema.EnumType('yes/no', {'yes', 'no'});
    end
 
    % add properties to class
    schema.prop(c, 'Editable', 'yes/no');
end

And our constructor is:

function self = taggedline
%OBJECT constructor for the simple.object class
    self = hg.taggedline;
end

Here we have placed the schema.EnumType definition in the class definition function. It is usually better to place type definition code in the package definition function, which is executed prior to any of the package classes and available in all classes. But in this particular case we are extending the built-in hg package and because hg is already defined internally, our package definition code is never actually executed.

The schema.UserType has the following constructor syntax:

schema.UserType('newTypeName', 'baseTypeName', typeCheckFunctionHandle)

For example, to create a user-defined type for unsigned eight-bit integers we might use the following code:

schema.UserType('uint8', 'short', @check_uint8)
 
function check_uint8(value)
%CHECK_UINT8 Check function for uint8 type definition
    if isempty(value) || (value < 0) || (value > 255)
        error('Value must be a scalar between 0 and 255');
    end
end

Hidden properties

Visible is an 'on/off' meta-property that controls whether or not a property is displayed when using the get function without specifying the property name. Using this mechanism we can easily detect hidden undocumented properties. For example:

>> for prop = get(classhandle(handle(gcf)),'Properties')'
       if strcmpi(prop.Visible,'off'), disp(prop.Name); end
   end
 
BackingStore
CurrentKey
CurrentModifier
Dithermap
DithermapMode
DoubleBuffer
FixedColors
HelpFcn
HelpTopicMap
MinColormap
JavaFrame
OuterPosition
ActivePositionProperty
PrintTemplate
ExportTemplate
WaitStatus
UseHG2
PixelBounds
HelpTopicKey
Serializable
ApplicationData
Behavior
XLimInclude
YLimInclude
ZLimInclude
CLimInclude
ALimInclude
IncludeRenderer

Note that hidden properties such as these are accessible via get/set just as any other property. It is simply that they are not displayed when you run get(gcf) or set(gcf) – we need to specifically refer to them by their name: get(gcf,’UseHG2′). Many other similar hidden properties are described in this website.

You may have noticed that the CaseSensitive meta-property did not show up above when we used get to show the meta-properties of our Value property. This is because CaseSensitive has its own Visible meta-property set to 'off' (i.e., hidden).

Additional meta-properties

FactoryValue is used to set an initial value for the property whenever a new simple.object instance is created.

GetFunction and SetFunction were described in last week’s article, Creating a UDD Hierarchy.

AccessFlags is a Matlab structure of 'on/off' fields that control what happens when the property is accessed:

FieldnameDescription
PublicSetControls setting the property from code external to the class
PublicGetControls reading the property value from code external to the class
PrivateSetControls setting the property from internal class methods
PrivateGetControls reading the property value from internal class methods
InitControls initializing the property using FactoryValue in the class definition file
Default??? (Undocumented, no examples exist)
ResetControls initializing the property using FactoryValue when executing the built-in reset function
SerializeControls whether this object can be serialized
CopyControls whether to pass the property’s current value to a copy
ListenerControls whether property access events are generated or not
AbortSetControls whether property set events are generated when a set operation will not change the property’s value

The CaseSensitive meta-property has AccessFlag.Init = 'off'. This means that properties added to a class definition file are always case insensitive.

Another interesting fact is that properties can be abbreviated as long as the abbreviation is unambiguous. Using our simple.object as an example:

>> a = simple.object('a');
>> a.n  % abbreviation of Name
ans =
a
 
>> a.v  % abbreviation of Value
ans =
    0.0000

It is considered poor programming practice to use either improperly cased, or abbreviated names when writing code. It is difficult to read, debug and maintain. But show me a Matlab programmer who has never abbreviated Position as ‘pos’…

Note: for completeness’ sake, read yesterday’s post on MCOS properties on Loren’s blog, written by Dave Foti, author of the original UDD code. Dave’s post describes the fully-documented MCOS mechanism, which is newer than the undocumented UDD mechanism described here. As mentioned earlier, whereas UDD existed (and still exists) in all Matlab 7 releases, MCOS is only available since R2008a. UDD and MCOS co-exist in Matlab since R2008a. MCOS has definite advantages over UDD, but cannot be used on pre-2008 Matlab releases. Different development and deployment requirements may dictate using either UDD or MCOS (or both). Another pre-R2008a alternative is to use Matlab’s obsolete yet documented class system.

In the next installment of this series we will take a look at UDD events and listeners.

Categories: Guest bloggers, Hidden property, Medium risk of breaking in future versions, Stock Matlab function, Undocumented feature

Tags: , , , , , ,

Bookmark and SharePrint Print

8 Responses to UDD Properties

  1. Maarten van der Seijs says:

    Hi Donn, thanks for your very interesting revelations on UDD so far! I see one additional advantage of UDD classes compared to MCOS, and that is the support for the MATLAB property inspector called by obj.inspect. The inspector automatically recognizes the datatypes used in the schema.m definitions and adds corresponding property editors and renderers. Unfortunately, this seems impossible with standard MCOS classes so far.

    In addition, the inspector allows us to group the properties in categories by implementing a class function info = getInspectorGrouping(h,arg). This function is very easy to define as well, since it should only return a cell array of categories and properties:

    info{1}{1} = 'Category1';
    info{1}{2} = {'prop1','prop2','prop3'};
    info{2}{1} = 'Category2';
    info{2}{2} = {'prop4','prop5'};
  2. Jonathan S says:

    Donn, I am very glad to finally get some insight into UDD classes in Matlab. Your articles so far have been fantastic.

    I may be jumping the gun just a little bit with my question, but I was attempting to create a class that subclasses hg.surface. Ideally, I would like to hide the XData property, however, if you attempt to modify the property in the schema.m file, it doesn’t allow changing the AccessFlags (since the superclass is already created). However, using your technique of overriding the property, I was able to generate a new XData property that is no longer visible. The question is, how does one go about accessing the XData property of a super class, since you still have to be able to manipulate the XData internally.

    Maybe this will be covered when you discuss the java behind UDD, but I can’t come up with a good way to do this.

    • Donn says:

      @Jonathan – To the best of my knowledge if you override a UDD property you will loose access to the SuperClass version (or if you prefer the superclass will loose access to the subclass version). If the valus of XData is fixed at the time of your subclass version you can pass it to the superclass in the constructor but you wont be able to change it afterwards.

      function obj = mySurface(xdataValue)
      %MYSURFACE constructor passes value of XData to superclass
          % Here the value is passed to the hg.surface superclass and
          % does not set the value of XData in the subclass.
          % Ref: uitools.uitab
          obj = hg.mySurface('XData', xdataValue);
      end

      Donn

  3. John says:

    Donn, thanks for all of the great info in these articles.

    Regarding property AccessFlags, do you have any insight into using the ‘PublicSet’ and ‘PublicGet’ meta-properties to create private (internal) properties? From what I’ve tried so far, setting these to ‘off’ prevents public access, which is the intention. It does not affect access from any methods in the @object folder, except that the constructor method does not appear to have access. Unfortunately, it also seems to prevent access from any sub-function of any class method, or from any set/get functions defined in schema.m.

    I’ve seen one way around this, in the scribe.colorbar class, by defining ‘getprivateprop’ and ‘setprivateprop’ methods and then using these throughout the rest of the code. This is clumsy to implement, and negates the whole idea of private access, since anyone can just call:

       hColorbar.setprivateprop('name',value')
       hColorbar.getprivateprop('name')

    to get access to the supposedly private property.

    Am I missing something? Is there a way to at least make the set/getprivateprop methods themselves private?

    • John says:

      A quick followup: The constructor method does have access to class properties regardless of the ‘PublicSet’ and ‘PublicGet’ access flags. Sorry for the misinformation.

    • Donn says:

      @John – Thanks for your kind words. You can place a private directory underneath your class directory. methods in that directory will not be available publicly but your regular methods will have access to them. I would guess that the method subfunction anomaly you have found was not intended and scribe.colorbar was a workaround. Try the private subfolder and les us know if it works for you.

      Donn

  4. Pingback: Undocumented classdef attributes | Undocumented Matlab

  5. Pingback: Setting class property types | Undocumented Matlab

Leave a Reply

Your email address will not be published. Required fields are marked *