Property listener with OOP

1 view (last 30 days)
Trevor Harris
Trevor Harris on 7 Sep 2016
Commented: Trevor Harris on 21 Sep 2016
Hello all,
I'm not exactly sure what I'm supposed to be asking here, so forgive me if I'm way off base. I have an object created in matlab with three properties. The class is called an nUnit, and the properties are value, unit, and unitVec. Both the unit and unitVec are heavily related to one another. So, if the user modifies the .unit, I wish for the .unitVec to be automatically updated and vice versa.
I have the conversion functions written, but how do I trigger them to run? I've read a lot about listeners and the like, but I can't seem to find a proper example for a function that would get triggered if a property is modified. Below is my class definition file. Thank you for your time!
Trevor
classdef nUnit
%NUNIT Create numerical unit class
%
% A = NUNIT(VALUE, UNITSTRING)
% A = NUNIT(VALUE, UNITVEC)
% Inputs:
% VALUE: Numeric scalar or array
% UNITSTRING: String of accepted unit strings
% UNITVEC: 1x9 numeric array of base unit powers
%
properties
value
unit
unitVec
end
methods
function nU = nUnit(value,unit)
% ==============================================================================
% Constructor - Create an nUnit
% ==============================================================================
if ~isnumeric(value) || isempty(value); error('input VALUE must be a non-empty numeric'); end
% If value is 1-dimensional, force vertical concatenation
if any(1 == size(value))
value = value(:);
end
if ~(ischar(unit) ||...
(isnumeric(unit) &&...
all(size(unit) == [1, 9]))); error('input UNIT must be a string or unitVector'); end %#ok<ALIGN>
if ischar(unit) % Unit string is inputed
[nU.unitVec, valueMult] = unit2vec(unit);
nU.unit = vec2unit(nU.unitVec);
nU.value = value * valueMult;
else % Unit vector is inputed - Base units only
nU.unitVec = unit;
nU.unit = vec2unit(unit);
nU.value = value;
end
end
% ==============================================================================
% Functions that only modify value property
% ==============================================================================
function nUnitA = diff(varargin); nUnitA = genValueFun(@diff, varargin{:}); end
function nUnitA = unique(varargin); nUnitA = genValueFun(@unique, varargin{:}); end
function nUnitX = genValueFun(functionH, nUnitX, varargin)
nUnitX.value = feval(functionH, nUnitX.value, varargin{:});
end
% ==============================================================================
% Overload Numel for O-O compatability
% Source: http://www.mathworks.com/matlabcentral/answers/101955-why-do-i-receive-errors-when-overloading-subsref-for-types-and-for-matlab-classes
% ==============================================================================
function n = numel(varargin)
n = 1;
end
% ==============================================================================
% Functions that query the value property
% ==============================================================================
function [varargout] = size(varargin)
varargout = genValueQueryFun(@size, varargin{:});
varargout = {varargout};
end
function [varargout] = length(varargin)
varargout = genValueQueryFun(@length, varargin{:});
varargout = {varargout};
end
function [varargout] = genValueQueryFun(functionH, nUnitX, varargin)
varargout = feval(functionH, nUnitX.value, varargin{:});
varargout = {varargout};
end
end
end

Accepted Answer

Adam
Adam on 7 Sep 2016
Edited: Adam on 7 Sep 2016
I use dependent properties for this, e.g.
properties
value
end
properties( Dependent )
unit
unitVec
end
properties( Access = private )
unit_;
unitVec_;
end
methods
function obj = set.unit( obj, unit )
unit_ = unit;
updateUnitVecFromUnit( obj );
end
function unit = get.unit( obj )
unit = obj.unit_;
end
function obj = set.unitVec( obj, unitVec )
unitVec_ = unitVec;
updateUnitFromUnitVec( obj );
end
function unitVec = get.unitVec( obj )
unitVec = obj.unitVec_;
end
end
methods( Access = private )
function updateUnitFromUnitVec( obj )
obj.unit_ = f( obj.unitVec_ );
end
function updateUnitVecFromUnit( obj )
obj.unitVec_ = f2( obj.unit_ );
end
end
There may be some errors in there as I did it off the top of my head, but the general idea is that only a dependent property is allowed to (or rather should do) alter other properties in its set function so you use a double property solution with a private property for each that actually stores the value and a dependent property which is publicly visible and whose set function will then update the other property also.
It is very important though that you update unit_ and unitVec_ in the functions as shown above otherwise you will have a circular set of calls that will lead you to infinite recursion! My code above just uses placeholder functions f and f2 instead of whatever it is you have already written to update one property from the other.
You could use a property listener. I do in many many cases, but not usually if I am doing something like this.
  1 Comment
Trevor Harris
Trevor Harris on 21 Sep 2016
Thanks so much, that's perfect! Very helpful.

Sign in to comment.

More Answers (0)

Categories

Find more on Get Started with MATLAB in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!