Object oriented – Undocumented Matlab https://undocumentedmatlab.com/blog_old Charting Matlab's unsupported hidden underbelly Tue, 29 Oct 2019 15:26:09 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.1 Setting class property types – take 2https://undocumentedmatlab.com/blog_old/setting-class-property-types-2 https://undocumentedmatlab.com/blog_old/setting-class-property-types-2#comments Wed, 27 Apr 2016 20:20:22 +0000 http://undocumentedmatlab.com/?p=6390 Related posts:
  1. Undocumented classdef attributes Matlab's object-oriented class definition enables usage of some useful undocumented attributes. ...
  2. Setting class property types Matlab's class properties have a simple and effective mechanism for setting their type....
  3. Class object tab completion & improper field names Tab completions and property access can be customized for user-created Matlab classes. ...
  4. Simulink Data Dictionary Simulink contains undocumented public API for access to its data dictionary functionality. ...
]]>
Three years ago, almost to the day, I wrote about a very handy undocumented feature of Matlab classes that enables us to specify type restrictions for any Matlab class property. We can specify property type (for example, char, double or any Matlab class) as well as dimensionality (scalar, vector, or matrix) and complexity indication (complex). Doing so has multiple benefits for code performance, robustness and maintainability. For example:

% Undocumented syntax - works well since at least R2010a (possibly earlier)
classdef Packet
    properties
        PacketType@char
        HeaderLength@uint16
        PayloadLength@uint16 scalar = uint16(0);  % initial value
        PacketData@uint8 vector
    end
end

In the recent release of Matlab R2016a, a similar feature have finally become fully supported and documented. The corresponding snippet above would look something like this:

% Documented syntax - only works in R2016a or newer
classdef Packet
    properties
        PacketType char
        HeaderLength uint16
        PayloadLength uint16 = uint16(0);  % initial value
        PacketData uint8
    end
end

Unfortunately, I dislike the new documented functionality, so I didn’t feel like promoting it in this blog when it came out. But since a blog reader mentioned it a few days ago, I wanted to come out publicly with my opinion and a detailed explanation.

If you look closely at the code snippets above, you will notice two important differences:

  1. The “@” symbol was replaced with a space
  2. The dimensionality and complexity cannot be specified

The new syntax has some drawbacks compared to the previous (undocumented) one:

  1. Backward compatibility – We can run the older (undocumented) syntax on any Matlab release since who-knows-when (at least as far back as R2010a [tested], and possibly older releases [untested]), including the very latest R2016a. On the other hand, the new (documented) syntax will only work on R2016a and will crash the program if you try to run it in older releases. This is not even something that you can catch with a try-catch block – the class will simply not load on any older Matlab release. If you need your code to run on older releases in addition to 16a, you have no choice other than to use the older syntax.
  2. Dimensionality – the new syntax, unlike the undocumented syntax, does not enable users to limit the data dimensionality (scalar/vector/array). This is a very important feature for program robustness and maintainability. Complexity is another type limitation that is missing, although it is less important than the dimensionality. And just in case you were wondering – the new syntax does not accept the additional scalar, vector, matrix and complex attributes like the older syntax; using them with the new syntax evokes an error.
  3. Cross compatibility – it is very confusing to users coming to Matlab from other programming languages, all of which (without any important exception) place the type name to the LEFT of the identifier name, not to its RIGHT. People coding in both Matlab and Java/C/C++ would easily get confused and frustrated.
  4. Consistency – despite what I hoped, the new syntax still does not apply to function input args: we cannot (AFAIK) limit the input/output args of methods/functions in the same way that we can limit properties. If there’s a way to do this, I’d be delighted to learn (this comment may indicate that it is work in progress). It is true that this feature is not a drawback of the new syntax compared to the older one, since the old syntax didn’t have it either (AFAIK). But I would have expected a documented feature to be consistent across the Matlab language (or at least across the MCOS subset), and unfortunately the new feature fails this test.

In fact, aside from the fact that the new syntax is documented, I can see no advantages that it offers over the older syntax, only disadvantages. Or am I missing something? Please do tell if you see any important advantages that I’ve missed.

Luckily for us, the old syntax remains operational, side-by-side with the new one. This enables us to keep running our existing code without worrying [too much] that it might break in R2016a. Maybe the new syntax will grow on me (or improve) in upcoming years, but for the time being I see no benefit in switching away from the @ syntax.

For the past few years, I hoped that the property typing feature will become documented and that it will be a continuation of the undocumented syntax rather than what eventually aired. I’m afraid it’s too late to revert it now that it has… Realistically speaking, the best we can hope for now is for the older syntax to remain operational, and not be withdrawn in some future Matlab release. Making the undocumented syntax documented as-is would be great, but I’m afraid it is unrealistic given the new circumstances.

I’m sorry if I take the wind off MathWorks’ sails a bit here, but MathWorks knows that it can count on me to speak my mind without bullshit. Sometimes for the good, sometimes not. All in good spirit and the common interest of improving Matlab over time. No offence intended – it’s just my personal opinion after all.

In my opinion this is one of those rare cases where the developers obviously intended to make something better but eventually came out with something worse. They should have stuck to what was. After all, the first and foremost rule of engineering is, and always was:

Don’t fix it if it ain’t broke!

]]>
https://undocumentedmatlab.com/blog_old/setting-class-property-types-2/feed 13
Setting class property typeshttps://undocumentedmatlab.com/blog_old/setting-class-property-types https://undocumentedmatlab.com/blog_old/setting-class-property-types#comments Thu, 18 Apr 2013 14:12:06 +0000 http://undocumentedmatlab.com/?p=3725 Related posts:
  1. Undocumented classdef attributes Matlab's object-oriented class definition enables usage of some useful undocumented attributes. ...
  2. Setting class property types – take 2 R2016a saw the addition of class property types. However, a better alternative has existed for many years. ...
  3. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  4. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
]]>
When I wrote about the undocumented aspects of classdef properties half a year ago, I did not expect to learn of another major undocumented aspect in Matlab’s class-object system. last month I discovered the additional undocumented classdef Description and DetailedDescription attributes, and updated that article accordingly. But a few days ago I was pleasantly surprised to read Amro’s comment about an entirely new and undocumented aspect of Matlab MCOS classes.

Amro is a top contributor on StackOverflow, where he frequently answers questions before I even get any subscription notification about them… His answers are generally characterized by a deep technical understanding of Matlab, and I’ve learned quite a lot from him in the past few years. This time was no different.

In a nutshell, Amro found an undocumented way to specify a class object property’s type, in such a way that would prevent accidental setting to an incompatible value. For example, if we have a class with properties Width and Height, we probably want to restrict their possible values to numbers, to prevent setting a string or struct value.

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.

We can still do this today, since UDD classes are still supported, side-by-side with the newer MCOS classes. Unfortunately, MCOS does not provide a documented way of specifying the property type as in UDD.

One simple way to prevent unintentional MCOS property updates is to override the property’s set method. In fact, this was the solution of Jonas, another StackOverflow heavyweight:

classdef myClass
   properties
      myProperty = uint16(23); %# specify default value using correct type
   end
   methods
      function obj = set.myProperty(obj,val)
         if ~isa(val,'uint16')
            error('only uint16 values allowed')
         end
         %# assign the value
         obj.myProperty = val;
      end
   end
end

But it turns out that there’s a much cleaner and simpler solution, provided by Amro:

classdef Packet
    properties
        HeaderLength@uint16
        PayloadLength@uint16 = uint16(0);
        PacketType@char
    end
end

As Amro notes, if you try to set a property with the wrong type, you get an error:

>> p = Packet;
>> p.PacketType = 'tcp';  % ok
>> p.HeaderLength = 100;  % not ok - should be a uint16
While setting the 'HeaderLength' property of Packet:
Value must be 'uint16'.

This syntax apparently supports all primitive types (char, int32, double, struct, cell etc.), in addition to any user-defined ones (just use any class name).

Note that setting the type as above seems to override any set method that may have been specified for the property.

Amro came across this syntax in an internal class in R2013a (toolboxdir(‘matlab’)/graphics/+graphics/+internal/+figfile/@FigFile/FigFile.m), but it also worked in R2012a, and probably older versions as well…

I admit there’s not much original work here by me – it’s basically all by Amro (and Donn Shull for the UDD part). But I thought it’s important enough to bring to the attention of the community.

I love to discover such undocumented treasures by digging in Matlab’s function. If you ever discover other such buried treasures, please do let me know by email or a comment.


Addendum June 21, 2013: As Sebastian Hölz mentioned in his comment below, the general syntax appears to be:

properties
   propName@className dimensionType = initialValue
end

where className, dimensionType and initialValue are optional elements:

  • className can be any Matlab class/type, such as double, single, or UserClass
  • dimensionType can be one of the following terms: scalar, vector, or matrix
  • the property may also be initiated with an initialValue (otherwise it receives a default value, depending on the property class)

Addendum August 12, 2014: In a related matter, we can limit the values that a property can accept using the matlab.system.StringSet class of the matlab.System package, as recently discovered by Oleg Komarov (additional details; additional aspects of class property tab-completion):

classdef foo < matlab.System
    properties
        Coordinates
    end
    properties(Hidden,Transient)
        CoordinatesSet = matlab.system.StringSet({'north','south','east','west'});
    end
end

restricting Matlab property values


Addendum April 8, 2015: As reported by Martin A. here and also below, R2015a has apparently added the new (and hidden) Type property to the meta.property class and the InputTypes and OutputTypes properties to the the meta.method class. This enables specifying and querying the types of properties as well as method inputs/outputs. For example:

mc = ?matlab.graphics.axis.Axes;
mc.PropertyList(1).Name % Camera
mc.PropertyList(1).Type % matlab.graphics.axis.camera.Camera
mc.MethodList(49).Name % addlistener
mc.MethodList(49).InputNames % [sources, propertyname, eventname, callback]
mc.MethodList(49).InputTypes % [handle, asciiString, char vector, function_handle scalar]

Addendum November 11, 2015: Apparently, when using the @double syntax, Matlab only allows the property to receive real values. In order to enable complex values, we can also add the undocumented “complex” attribute. Note that we have to enter the dimensionality (scalar/vector/matrix) first, since “complex” is not accepted as a valid dimensionality value. For example:

% This is ok:
classdef foo
    properties
        bar@double scalar complex = 1 + 2i    end
end
 
% This causes an error:
classdef foo
    properties
        bar@double complex = 1 + 2i    end
end

Addendum April 28, 2016: Matlab R2016a now has a similar documented functionality. However, I feel that there are important drawbacks to the new functionality compared to the one presented here. Read the full discussion about this.

The new (documented) syntax automatically type-casts the data to the specified data type, were possible, something that the undocumented (@) syntax presented above does not. In other words, the undocumented syntax is stricter and expects the data to be exactly the specified data type, without attempting any type-casting. As reported by Martin Afanasjew, we can add the property attribute to the data type to replicate the new syntax’s automatic type-casting:

classdef foo
    properties
        prop1@char = 'A'  % will only accept char inputs, not numeric values
        prop2@char property = 65  % will automatically type-cast: 65 will be converted to 'A'    end
end
]]>
https://undocumentedmatlab.com/blog_old/setting-class-property-types/feed 37
Undocumented classdef attributeshttps://undocumentedmatlab.com/blog_old/undocumented-classdef-attributes https://undocumentedmatlab.com/blog_old/undocumented-classdef-attributes#comments Wed, 21 Nov 2012 18:00:54 +0000 http://undocumentedmatlab.com/?p=3315 Related posts:
  1. Setting class property types Matlab's class properties have a simple and effective mechanism for setting their type....
  2. Setting class property types – take 2 R2016a saw the addition of class property types. However, a better alternative has existed for many years. ...
  3. Class object tab completion & improper field names Tab completions and property access can be customized for user-created Matlab classes. ...
  4. Simulink Data Dictionary Simulink contains undocumented public API for access to its data dictionary functionality. ...
]]>
Matlab’s new (or should I say “renewed”) object-oriented paradigm, uses attributes to define class behavior. Not surprisingly, some attributes used by Matlab’s internal classes are not documented in the official documentation of the supported attributes. These attributes could well be useful when defining our custom classes:

MCOS (Matlab Common/Class Object System) classes

Attribute NameClassDefault value if unspecifiedDescription
CaseInsensitivePropertieslogical (true/false)falseIf true, then such properties can be accessed using any case. For example, if the property is called myProp, then it can be called as myclass.myProp or myClass.MYPROP or any other variation.

If the class inherits hgsetget, then the property can also be used in this way within get/set functions:

get(myClass,'MYPROP')

If the attribute is unspecified or false, then trying to use a case-insensitive version of the property name would result in an error:

Error using MyClass/get
Property MYPROP not found in class MyClass, or is not present in all elements of the array of class MyClass.

TruncatedPropertieslogical (true/false)falseIf true, then such properties can be accessed using any substring that leads to a unique property. For example, if the property is called myProperty, then it can be called as myclass.myProperty or myClass.myProp or any other variation.

If the class inherits hgsetget, then the property can also be used in this way within get/set functions:

get(myClass,'myProp')

Note that if the class has another property called myProblem, then myClass.myPro would be ambiguous and result in an error message; we would need to use myClass.myProp or some other unique term:

Error using MyClass/get
Ambiguous MyClass property: 'myPro'.

If the attribute is unspecified or false, then trying to use a truncated version of the property name would result in an error:

Error using MyClass/get
Property myProp not found in class MyClass, or is not present in all elements of the array of class MyClass.

Enumerationlogical (true/false)falseIf true, then the class appears to be an enumeration class. I am not exactly sure how this could be useful. I saw references to this attribute in the Data Aquisition Toolbox.
SupportClassFunctionslogical (true/false)falseAs above, I am not exactly sure how this could be useful. I saw reference to this attribute in %matlabroot%/toolbox/shared/controllib/engine/ (I don’t currently have ready access to this toolbox so I can’t test).
Descriptionchar''A string that describes the class. First mentioned here.
DetailedDescriptionchar''A string that describes the class in more detail. First mentioned here.

The CaseInsensitiveProperties and TruncatedProperties attributes are true for Matlab HG (Handle-Graphics) properties. Many users have come to rely on the fact that they can specify the Position property using get(gcf,'position') or set(gcf,'Pos'). It is very intuitive to use. For this reason I do not understand why MathWorks chose to set these attributes’ default value to false. At least now we can manually change this for our classes.

Sample usage (see %matlabroot%/toolbox/matlab/graphics/+graphics/+internal/@LinkAxes/LinkAxes.m and many others):

classdef (CaseInsensitiveProperties=true, TruncatedProperties=true, ConstructOnLoad=true) LinkAxes < handle
classdef (CaseInsensitiveProperties, TruncatedProperties, ConstructOnLoad) LinkAxes < handle  % equivalent alternative

I could not find any similar undocumented attributes for properties, methods, events and enumerations.

Do you know of any other useful attribute for the class, or for its constituents? If so, please post a short comment below.

UDD (Universal Data Dictionary, schema) classes

UDD (schema) classes have the property truncation on by default, and in fact this cannot be unset. I.e., we cannot have a variant of MCOS’s TruncatedProperties=false for schema objects:

>> hTabGroup = uitabgroup;
>> get(hTabGroup,'FlowDir')  % truncated from 'FlowDirection'
ans =
topdown

The properties do have a settable CaseSensitive meta-property that we can set to ‘on/off’ (default=’off’) on a property-by-property basis. In most cases, we would naturally stick with the default behavior:

>> get(hTabGroup,'flowdir')  % case-insensitive form of 'FlowDirection'
ans =
topdown

This mean that by default, schema objects behave similarly to the ubiquitous HG behavior, whereas custom MCOS objects have a default behavior that is much stricter and needs special handling.

]]>
https://undocumentedmatlab.com/blog_old/undocumented-classdef-attributes/feed 19