- Undocumented Matlab - https://undocumentedmatlab.com -

UDD Properties

Posted By Yair Altman On March 9, 2011 | 8 Comments

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 [1], 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:

Property Data Type Description
AccessFlags Matlab structure Controls which objects can access (read/modify) the property
CaseSensitive on/off Determines if the exact case is required to access the property (i.e., can we use ‘casesensitive’ instead of ‘CaseSensitive’)
DataType string The underlying object’s property data type, set by the constructor
Description string This can hold a description of the property (normally empty)
FactoryValue As specified by DataType This is used to provide an initial or default property value
GetFunction Function handle A function handle that is called whenever the property value is read
Name string The name of the property, also set by the constructor
SetFunction Function handle A function handle that is called whenever the properties value is changed
Visible on/off Determines 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 [1] 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:

Category Data Type
Universal MATLAB array, mxArray
Numeric Scalars bool, byte, short, int, long, float, double
Numeric Vectors Nints, NReals
Specialized Numeric color, point, real point, real point3, rect, real rect
Enumeration on/off
Strings char, string, NStrings, string vector
Handle handle, handle vector, MATLAB callback, GetFunction, SetFunction
Java Any 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 [2] 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
    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 [3].
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 [4].
AccessFlags is a Matlab structure of 'on/off' fields that control what happens when the property is accessed:

Fieldname Description
PublicSet Controls setting the property from code external to the class
PublicGet Controls reading the property value from code external to the class
PrivateSet Controls setting the property from internal class methods
PrivateGet Controls reading the property value from internal class methods
Init Controls initializing the property using FactoryValue in the class definition file
Default ??? (Undocumented, no examples exist)
Reset Controls initializing the property using FactoryValue when executing the built-in reset function
Serialize Controls whether this object can be serialized
Copy Controls whether to pass the property’s current value to a copy
Listener Controls whether property access events are generated or not
AbortSet Controls 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 [5] 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 [6].
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


8 Comments (Open | Close)

8 Comments To "UDD Properties"

#1 Comment By Maarten van der Seijs On March 10, 2011 @ 02:51

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 Comment By Jonathan S On March 13, 2011 @ 18:31

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.

#3 Comment By Donn On March 15, 2011 @ 09:06

@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

#4 Comment By John On March 24, 2011 @ 08:47

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?

#5 Comment By John On March 24, 2011 @ 09:10

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

#6 Comment By Donn On March 24, 2011 @ 10:40

@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

#7 Pingback By Undocumented classdef attributes | Undocumented Matlab On November 21, 2012 @ 11:02

[…] The properties do have a settable CaseSensitive meta-property that we can set to 'on/off' (default='off') on a property-by-property basis. […]

#8 Pingback By Setting class property types | Undocumented Matlab On June 21, 2013 @ 03:29

[…] In UDD classes, we can do this easily by setting the property’s DataType meta-property. An easy way to do this is by setting the second argument of the schema.prop function. A detailed explanation was provided here. […]


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/udd-properties

URLs in this post:

[1] already shown: http://undocumentedmatlab.com/blog/creating-a-simple-udd-class/

[2] problem discussed in the CSSM forum: https://www.mathworks.com/matlabcentral/newsreader/view_thread/280282

[3] described in this website: http://undocumentedmatlab.com/blog/tag/hidden-property/

[4] Creating a UDD Hierarchy: http://undocumentedmatlab.com/blog/hierarchical-systems-with-udd/

[5] MCOS properties: http://blogs.mathworks.com/loren/2011/03/08/common-design-considerations-for-object-properties/

[6] class system: http://www.mathworks.com/help/pdf_doc/matlab/pre-version_7.6_oop.pdf

[7] Displaying hidden handle properties : https://undocumentedmatlab.com/articles/displaying-hidden-handle-properties

[8] getundoc – get undocumented object properties : https://undocumentedmatlab.com/articles/getundoc-get-undocumented-object-properties

[9] Plot LimInclude properties : https://undocumentedmatlab.com/articles/plot-liminclude-properties

[10] Adding dynamic properties to graphic handles : https://undocumentedmatlab.com/articles/adding-dynamic-properties-to-graphic-handles

[11] Customizing axes part 4 – additional properties : https://undocumentedmatlab.com/articles/customizing-axes-part-4-additional-properties

[12] Performance: accessing handle properties : https://undocumentedmatlab.com/articles/performance-accessing-handle-properties

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.