Reputation: 185
I am fairly new to Matlab, and I was wondering if there is a way to create a "one-way handle class".
To explain better, lets say I have a class called test_class, with properties "prop1" and "prop2"
test_1 = test_class(5,10)
test_2 = test_1
I wanted changes applied to properties within test_1 (parent) to affect test_2 (child), but I do not want changes in test_2 to affect test_1, so
test_1.prop1 = 20;
test_2.prop1: 20
test_2.prop2 = 30;
test_1.prop2: 5
Is there a way to create such a "one-way dependecy"?
Thanks in advance!
Upvotes: 4
Views: 89
Reputation: 2187
You can do this without getting into the difficulties of subasgn by leveraging property set listeners. This way you don't need ot get in the business of holding on to and managing all of the children copies. This looks something like the following:
classdef test_class < matlab.mixin.Copyable
properties(SetObservable)
prop1
prop2
end
properties
prop3
end
methods
function obj = test_class(in1, in2, in3)
obj.prop1 = in1;
obj.prop2 = in2;
obj.prop3 = in3;
end
function ref = make_dependent_reference(obj)
ref = copy(obj);
cls = metaclass(obj);
observableProps = cls.PropertyList.findobj('SetObservable',true);
for ct =1:numel(observableProps)
obj.addlistener(observableProps(ct).Name, 'PostSet', ...
@(prop,evd)ref.update_dependent_reference(prop,evd));
end
end
end
methods(Access=private)
function update_dependent_reference(ref, prop, evd)
ref.(prop.Name) = evd.AffectedObject.(prop.Name);
end
end
end
Note, this requires the properties to be SetObservable
, you can either choose to make the reference updates to those properties ignore properties that are not SetObservable
like I've shown above with the findobj call or you can instead operate on all properties and let the addlistener call error out for any properties that are not SetObservable
.
>> t = test_class(5,10,15)
t =
test_class with properties:
prop1: 5
prop2: 10
prop3: 15
>> ref = t.make_dependent_reference
ref =
test_class with properties:
prop1: 5
prop2: 10
prop3: 15
>> ref.prop1 = 6
ref =
test_class with properties:
prop1: 6
prop2: 10
prop3: 15
>> t
t =
test_class with properties:
prop1: 5
prop2: 10
prop3: 15
>> t.prop2 = 11
t =
test_class with properties:
prop1: 5
prop2: 11
prop3: 15
>> ref
ref =
test_class with properties:
prop1: 6
prop2: 11
prop3: 15
Upvotes: 4
Reputation: 15837
Here is a basic implementation. Each object has a parent and an array of children. Using subsasgn
we can change properties of the object and its children and because the object is one-way we don't want to change properties of the parent.
Usage:
a = oneway(1,2);
b = oneway(a);
c = oneway(b);
If we set a.prop1 = 7;
then b
will be changed that leads to change of c
. If you want only to change the direct children you can uncomment line 31
and comment line 30
.
classdef oneway < handle
properties
parent
children={};
end
properties
prop1
prop2
end
methods
function obj = oneway(varargin)
if nargin == 1
a = varargin{1};
if isa(a,'oneway')
obj.prop1 = a.prop1;
obj.prop2 = a.prop2;
obj.parent = a;
a.children{end+1} = obj;
end
elseif nargin == 2
obj.prop1 = varargin{1};
obj.prop2 = varargin{2};
end
end
function obj = subsasgn(self, S, B)
if strcmp(S.type, '.')
if ismember(S.subs, properties(self))
obj = builtin('subsasgn', self, S, B);
for k = 1: numel(self.children)
self.children{k} = subsasgn(self.children{k},S,B);
%self.children{k} = builtin('subsasgn', self.children{k}, S, B);
end
end
end
end
function delete(self)
self.parent.children (cellfun(@(x)x==self,self.parent.children))=[];
for k = 1: numel(self.children)
self.children{k}.parent =[];
end
end
end
end
Upvotes: 3
Reputation: 3608
I don't think this is possible. You can either have copies of handle objects which refer to the same underlying object (2-way dependent) or value objects where copies are independent of each other. Object behavior.
You might be able to create value object which has a Property
that contains a handle ... so part of the you object is 2-way and part is 1-way. But that isn't really what you asked for.
Upvotes: 0