|On this page…|
You can attach properties to objects without defining these properties in the class definition. These dynamic properties are sometimes referred to as instance properties. Use dynamic properties to attach temporary data to objects or assign data that you want to associate with a particular instance of a class, but not all objects of that class.
It is possible for more than one program to define dynamic properties on the same object so you must take care to avoid name conflicts.
Once defined, dynamic properties behave much like class-defined properties:
Set and query the values of dynamic properties using dot notation (see Assigning Data to the Dynamic Property)
Define attributes for dynamic property (see Setting Dynamic Property Attributes).
Add property set and get access methods (see Defining Property Access Methods for Dynamic Properties)
Listen for dynamic property events (see Responding to Dynamic-Property Events)
Access dynamic property values from object arrays, with restricted syntax (see Object Arrays with Dynamic Properties)
Any class that is a subclass of the dynamicprops class (which is itself a subclass of the handle class) can define dynamic properties using the addprop method. The syntax is:
P = addprop(H,'PropertyName')
P is an array of meta.DynamicProperty objects
H is an array of handles
PropertyName is the name of the dynamic property you are adding to each object
Use only valid names when naming dynamic properties (see Variable Names). In addition, do not use names that:
Are the same as the name of a class method
Are the same as the name of a class event
Contain a period (.)
Use the meta.DynamicProperty object associated with the dynamic property to set property attributes. For example:
P.Hidden = true;
Remove the dynamic property by deleting its meta.DynamicProperty object:
The property attributes Constant and Abstract have no meaning for dynamic properties and setting the value of these attributes to true has no effect.
Suppose, you are using a predefined set of GUI widget classes (buttons, sliders, check boxes, etc.) and you want to store the location on a grid of each instance of the widget class. Assume the widget classes are not designed to store location data for your particular layout scheme and you want to avoid creating a map or hash table to maintain this information separately.
Assuming the button class is a subclass of dynamicprops, you could add a dynamic property to store your layout data. Here is a simple class to create a uicontrol button:
classdef button < dynamicprops properties UiHandle end methods function obj = button(pos) if nargin > 0 if length(pos) == 4 obj.UiHandle = uicontrol('Position',pos,... 'Style','pushbutton'); else error('Improper position') end end end end end
Create an instance of the button class, add a dynamic property, and set its value:
b1 = button([20 40 80 20]); % button class uses HG-type position layout b1.addprop('myCoord'); % Add a dynamic property b1.myCoord = [2,3]; % Set the property value
You can access the dynamic property just like any other property, but only on the instance on which you defined it:
b1.myCoord ans = 2 3
You can attach listeners to dynamicprops objects to monitor the addition of dynamic properties to the object. You can also monitor the removal of dynamic properties, which occurs when you delete the object.
The dynamicprops class defines two events and inherits one from handle:
ObjectBeingDestroyed — Inherited from the handle class.
PropertyAdded — Triggered when you add a dynamic property to an object derived from the dynamicprops class.
PropertyRemoved — Triggered when you delete the meta.DynamicProperty object associated with the dynamic property.
Suppose you define a button object, as described in the previous section:
b2 = button([20 40 80 20]);
Create a function to attach listeners to the button object, b2, and a listener callback function:
function listenDynoEvent(obj) addlistener(obj,'PropertyAdded',@eventPR); addlistener(obj,'PropertyRemoved',@eventPR); function eventPR(src,evnt) mc = metaclass(src); fprintf(1,'%s %s \n',mc.Name,'object') fprintf(1,'%s %s \n','Event triggered:',evnt.EventName) end end
Add the listeners to the button object, b2. Then, add a dynamic property, myCoord.
% add listeners listenDynoEvent(b2) % add dynamic property and save meta.DynamicProperty object mp = b2.addprop('myCoord');
The listener callback function, eventPR, executes and displays the object class and event name:
button object Event triggered: PropertyAdded
Delete the dynamic property by deleting the meta.DynamicProperty object:
delete(mp) button object Event triggered: PropertyRemoved
Obtain the meta.DynamicProperty object for a dynamic property using the handle findprop method. Use findprop if you do not have the object returned by addprop:
mp = findprop(b2,'myCoord');
Dynamic properties support property set and get events so you can define listeners for these properties. Listeners are bound to the particular dynamic property for which you define them. Therefore, if you delete a dynamic property, and then create another one with the same name, the listeners do not respond to events generated by the new property, even though the property has the same name as the property for which the event was defined.
Having a listener defined for a deleted dynamic property does not cause an error, but the listener callback is never executed.
Property-Set and Query Events provides more information on how to define listeners for these events.
Dynamic properties enable you to add properties to class instances without modifying class definitions. You can also define property set access or get access methods without creating new class methods. See Property Setter and Getter Methods for more on the purpose and techniques of these methods.
Note: You can set and get the property values only from within your property access methods. You cannot call another function from the set or get method and attempt to access the property value from that function.
Here are the steps for creating a property access method:
Define a function that implements the desired operations you want to perform before the property set or get occurs. These methods must have the following signatures: mySet(obj,val) or val = myGet(obj)
Obtain the dynamic property's corresponding meta.DynamicProperty object.
Assign a function handle pointing to your set or get property function to the meta.DynamicProperty object's GetMethod or SetMethod property. This function does not need to be a method of the class and you cannot use a naming scheme like set.PropertyName. Instead, use any valid function name.
Suppose you want to create a property set function for the button class dynamic property myCoord created previously. Write the function as follows:
function set_myCoord(obj,val) if ~(length(val) == 2) % require two values error('myCoords require two values ') end obj.myCoord = val; % set property value end
Because button is a handle class, the property set function does not need to return the object as an output argument. Assign the value to the property if the value is valid.
Use the handle class method findprop to get the meta.DynamicProperty object:
mb1 = b1.findprop('myCoord'); mb1.SetMethod = @set_myCoord;
The property set function is now called whenever you set this property:
b1.myCoord = [1 2 3] % length must be two Error using button.set_myCoord myCoords require two values
Setting a class's ConstructOnLoad attribute to true causes MATLAB to call the class constructor when loading the class. Dynamic properties are saved and restored when loading an object. If you are creating dynamic properties from the class constructor, you can cause a conflict if you also set the class's ConstructOnLoad attribute to true. Here's the sequence:
A saved object saves the names and values of properties, including dynamic properties
When loaded, a new object is created and all properties are restored to the values at the time the object was saved
Then, the ConstructOnLoad attribute causes a call to the class constructor, which would create another dynamic property with the same name as the loaded property (see The Default Save and Load Process for more on the load sequence)
MATLAB prevents a conflict by loading the saved dynamic property, and does not execute addprop when calling the constructor.
If it is necessary for you to use ConstructOnLoad and you add dynamic properties from the class constructor (and want the constructor's call to addprop to be executed at load time) then set the dynamic property's Transient attribute to true. This setting prevents the property from being saved. For example:
classdef (ConstructOnLoad) MyClass < dynamicprops function obj = MyClass P = addprop(obj,'DynProp'); P.Transient = true; ... end end