Creating a hard link among properties of an object?

3 views (last 30 days)
Hello,
I have a class called Module that has 3 properties: InternalVariables, ExternalVariables, and AllVariables. InternalVariables and ExternalVariables both contain symbolic column vectors. I want to define AllVariables as the superposition of InternalVariables and ExternalVariables, and if I change either InternalVariables or ExternalVariables, AllVariables gets updated automatically. Is there a way to do this by using a hard link?
Thank you,
Kevin

Accepted Answer

Sean de Wolski
Sean de Wolski on 13 May 2014
A couple of thoughts
Why not just make AllVariables a dependent property. Then every time it's queried it's calculated on the fly. MATLAB passes by reference so unless you have thousands of variables this should not be a performance penalty.
Another approach would be with listeners. The basic plan would be to have the constructor set listeners for changes to internal and external properties. This avoids having to have an explicit setter for each property. Of course, having an explicit setter for each property isn't necessarily a bad thing, especially if you need to validate the new property values anyway. In fact, I would probably just take this approach and use a setter every time.
  4 Comments
Cedric
Cedric on 13 May 2014
Edited: Cedric on 13 May 2014
I built really fast a dummy example to illustrate
classdef TestClass < handle
properties
intVars
extVars
allVars
end
methods
function obj = TestClass()
obj.intVars = struct( 'a', 8:15, 'b', -3 ) ;
obj.extVars = struct( 'c', 7, 'd', 8 ) ;
end
function value = get.intVars( obj ), value = obj.intVars ; end
function set.intVars( obj, value ), obj.intVars = value ; end
function value = get.extVars( obj ), value = obj.extVars ; end
function set.extVars( obj, value ), obj.extVars = value ; end
function value = get.allVars( obj )
% If accessing e.g. TestClass.allVars.c, how do I know here
% that field 'c' was addressed => how can I pick extVars?
end
function set.allVars( obj, value )
% If accessing e.g. TestClass.allVars.c, how do I know here
% that field 'c' was addressed => how can I pick extVars?
end
end
end
On that note, have a good night! I'll be back tomorrow to go on the discussion.
Sean de Wolski
Sean de Wolski on 13 May 2014
I don't have much time right now (so will probably have to continue this tonight) but here the better of the two approaches I had in mind:
In the getter (recommended!)
classdef TestClass < handle
properties
intVars
extVars
end
properties (SetAccess = protected, Transient = true, Dependent = true)
allVars
end
methods
function obj = TestClass()
obj.intVars = struct( 'a', 8:15, 'b', -3 ) ;
obj.extVars = struct( 'c', 7, 'd', 8 ) ;
end
function val = get.allVars(obj)
val = obj.intVars;
fns = fieldnames(obj.extVars);
for ii = 1:numel(fns)
val.(fns{ii}) = obj.extVars.(fns{ii});
end
end
end
end
To use it:
T = TestClass
T.allVars
T.intVars.Hwllo = pi
T.allVars
T.extVars.World = exp(1)
T.allVars

Sign in to comment.

More Answers (1)

Cedric
Cedric on 12 May 2014
Edited: Cedric on 13 May 2014
NOTE: well, I spent an hour stuck in a mall with a tornado warning, so I had a little time to extend my first example. See EDIT below.
Did you try using setters and getters for these properties (in conjunction with dependent properties)? If they are stored in structs (and not as public/private/etc groups of properties), you may have to use subsasgn / subsref / substruct, etc.
EDIT : here is a new version of my previous example, which delegates indexing appropriately (I suppose, but I didn't have time to test) when fields of allVars contain arrays or structs.
classdef TestClass < handle
properties
intVars
extVars
allVars
end
methods
function obj = TestClass()
obj.intVars = struct( 'aInt', 3, 'bInt', 20:30, 'c', 7 ) ;
obj.extVars.dExt = struct( 'x', -2, 'y', 48 ) ;
obj.extVars.eExt = {'Hello', 'World'} ;
obj.extVars.c = 8 ;
end
function value = subsref( obj, S )
if length(S) > 1 && all( [S(1:2).type] == '.' ) && ...
strcmp( S(1).subs, 'allVars' )
is_int = isfield( obj.intVars, S(2).subs ) ;
is_ext = isfield( obj.extVars, S(2).subs ) ;
if is_int && is_ext
valueInt = obj.subsref_delegate( obj.intVars.(S(2).subs), S ) ;
valueExt = obj.subsref_delegate( obj.extVars.(S(2).subs), S ) ;
value = struct( 'int', valueInt, 'ext', valueExt ) ;
elseif is_int
value = obj.subsref_delegate( obj.intVars.(S(2).subs), S ) ;
else
value = obj.subsref_delegate( obj.extVars.(S(2).subs), S ) ;
end
else
value = builtin( 'subsref', obj, S ) ;
end
end
function obj = subsasgn_TODO( obj, S, value )
% .. your move.
end
end
methods (Static)
function value = subsref_delegate( x, S )
if length( S ) > 2
value = builtin( 'subsref', x, S(3:end) ) ;
else
value = x ;
end
end
end
end
With that..
>> tc = TestClass() ;
>> tc.intVars
ans =
aInt: 3
bInt: [20 21 22 23 24 25 26 27 28 29 30]
c: 7
>> tc.extVars
ans =
dExt: [1x1 struct]
eExt: {'Hello' 'World'}
c: 8
>> tc.extVars.dExt.x
ans =
-2
>> tc.allVars.aInt
ans =
3
>> tc.allVars.bInt
ans =
20 21 22 23 24 25 26 27 28 29 30
>> tc.allVars.bInt(7)
ans =
26
>> tc.allVars.c % c is a common property => output struct with int/ext values.
ans =
int: 7
ext: 8
>> tc.allVars.eExt{2}
ans =
World
>> tc.allVars.dExt.y
ans =
48
  4 Comments
Sean de Wolski
Sean de Wolski on 14 May 2014
Interesting comment on the tornado warning - I wonder if it was the same one that kept me at the hotel yesterday outside of Detroit.

Sign in to comment.

Categories

Find more on Variables 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!