如何在 Matlab 句柄 class 中创建 "one-way dependency"
How to create a "one-way dependency" within Matlab handle class
我是 Matlab 的新手,我想知道是否有办法创建 "one-way handle class"。
为了更好地解释,假设我有一个名为 test_class 的 class,其属性为 "prop1" 和 "prop2"
test_1 = test_class(5,10)
test_2 = test_1
我希望对 test_1(父级)中的属性应用的更改会影响 test_2(子级),但我不希望 test_2 中的更改影响 test_1 , 所以
test_1.prop1 = 20;
test_2.prop1: 20
test_2.prop2 = 30;
test_1.prop2: 5
有没有办法创建这样的"one-way dependecy"?
提前致谢!
我认为这是不可能的。您可以拥有引用相同底层对象(2 向依赖)的句柄对象的副本,也可以拥有副本彼此独立的值对象。 Object behavior.
您也许能够创建具有 Property
的值对象,其中包含一个句柄...所以您对象的一部分是 2 向的,部分是 1 向的。但这并不是你真正想要的。
这是一个基本的实现。每个 object 都有一个 parent 和一个 children 的数组。使用 subsasgn
我们可以更改 object 及其 children 的属性,因为 object 是 one-way 我们不想更改 parent.
用法:
a = oneway(1,2);
b = oneway(a);
c = oneway(b);
如果我们设置 a.prop1 = 7;
,那么 b
将被更改,从而导致 c
的更改。如果您只想更改直接 children 您可以取消注释行 31
和注释行 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
您可以通过利用 属性 设置侦听器来执行此操作而不会遇到 subasgn 的困难。这样,您就无需参与保留和管理所有子副本的业务。这看起来类似于以下内容:
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
请注意,这要求属性为 SetObservable
,您可以选择对这些属性进行引用更新,忽略不属于 SetObservable
的属性,就像我上面用 findobj 显示的那样调用,或者您可以改为对所有属性进行操作,并让 addlistener 为任何不是 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
我是 Matlab 的新手,我想知道是否有办法创建 "one-way handle class"。
为了更好地解释,假设我有一个名为 test_class 的 class,其属性为 "prop1" 和 "prop2"
test_1 = test_class(5,10)
test_2 = test_1
我希望对 test_1(父级)中的属性应用的更改会影响 test_2(子级),但我不希望 test_2 中的更改影响 test_1 , 所以
test_1.prop1 = 20;
test_2.prop1: 20
test_2.prop2 = 30;
test_1.prop2: 5
有没有办法创建这样的"one-way dependecy"?
提前致谢!
我认为这是不可能的。您可以拥有引用相同底层对象(2 向依赖)的句柄对象的副本,也可以拥有副本彼此独立的值对象。 Object behavior.
您也许能够创建具有 Property
的值对象,其中包含一个句柄...所以您对象的一部分是 2 向的,部分是 1 向的。但这并不是你真正想要的。
这是一个基本的实现。每个 object 都有一个 parent 和一个 children 的数组。使用 subsasgn
我们可以更改 object 及其 children 的属性,因为 object 是 one-way 我们不想更改 parent.
用法:
a = oneway(1,2);
b = oneway(a);
c = oneway(b);
如果我们设置 a.prop1 = 7;
,那么 b
将被更改,从而导致 c
的更改。如果您只想更改直接 children 您可以取消注释行 31
和注释行 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
您可以通过利用 属性 设置侦听器来执行此操作而不会遇到 subasgn 的困难。这样,您就无需参与保留和管理所有子副本的业务。这看起来类似于以下内容:
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
请注意,这要求属性为 SetObservable
,您可以选择对这些属性进行引用更新,忽略不属于 SetObservable
的属性,就像我上面用 findobj 显示的那样调用,或者您可以改为对所有属性进行操作,并让 addlistener 为任何不是 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