Using function handles with private properties and private methods

21 次查看(过去 30 天)
Hello, everyone. I have been experimenting with the use of function handles on classes with private methods and/or have private properties. I have provided a simple example class below. I am currently using Matlab R2023a, but I also got the same results using Matlab R2019b.
classdef test % < handle
properties (Access = private)
this
that
testVar
end
properties (Access = private)
fn
end
methods (Access = public)
function obj = test( accessSwitch )
obj.this = 'This';
obj.that = 'That';
obj.testVar = 2;
if ( accessSwitch )
obj.fn = @obj.takeThat;
obj.testVar = 1;
obj.that = '123';
elseif (~accessSwitch)
obj.fn = @obj.considerThis;
obj.testVar = 2;
obj.this = '456';
else
error('not hitting the above cases');
end
end
function processTest(testObj)
testObj.fn();
end
end
methods (Access = private)
function takeThat( obj )
fprintf( '%s\n', obj.that );
end
function considerThis( obj )
fprintf( '%s\n', obj.this );
end
end
end
I tested this class with the accessSwitch set both to 0 and 1. I set a breakpoint in the debugger at the point where the "takeThat" or "considerThis" function is called. In both cases, the private properties are not updated. "testVar" remains as 2, even if the accessSwitch is 1. Additionally, the "that" and "this" properties are not modified to "123" or "456" either. It appears that when the function handle is defined, it saves the current values of the properties and does not account for further modifications of the properties.
Correct me if I am mistaken, but creating a function handle shouldn't restrict any further modifications to the values of the private properties, correct? I continued to experiment and noticed that creating the function handle after changing the property values instead results in "testVar" and "that" using "1" and "123" respectively when calling the "processTest" function (see code block below). This is the result I would have expected from the original implementation above.
if ( accessSwitch )
obj.testVar = 1;
obj.that = '123';
obj.fn = @obj.takeThat;
Is this importance of where you create your function handle intentional? If so, why?
Lastly, I am aware that uncommenting the section in the classdef line (i.e., making it a handle class) effectively prevents the problem. However, I would prefer not to define a handle class, as the ability to assign a handle object to multiple variables can be dangerous. I would like to mitigate this risk.
Thank you for your help.
.

采纳的回答

Neha
Neha 2023-5-31
Hi Austin,
I understand that you want to know if subsequent modifications to the object's properties affect the captured state stored in the function handle. Since the current state is captured when a function handle is created, changes in object properties are not reflected.
To address this issue, one approach is to use an anonymous function to create the function handle instead of directly capturing the object's method.
obj.fn = @(obj) obj.takeThat();
By using an anonymous function, the object "obj" is passed as an argument to the function handle, ensuring that it accesses the current state of the object's properties when called, rather than at the time of creation. The same can be implemented for the "considerThis" function.
Hope this helps!
  6 个评论
Eric Klingler
Eric Klingler 2023-6-1
If I understand this correctly, there really is no such thing as a "simple" function handle. All function handles are treated as anonymous function handles with varargin as the argument. Is this detail mentioned in the documentation?
Thanks again for the clarification,
Eric
Walter Roberson
Walter Roberson 2023-6-1
h1 = @sin
h1 = function_handle with value:
@sin
h2 = @(x) sin(x+0)
h2 = function_handle with value:
@(x)sin(x+0)
c = 0; h3 = @(x) sin(x+c)
h3 = function_handle with value:
@(x)sin(x+c)
info1 = functions(h1)
info1 = struct with fields:
function: 'sin' type: 'simple' file: ''
Notice the 'type', 'simple'
info2 = functions(h2)
info2 = struct with fields:
function: '@(x)sin(x+0)' type: 'anonymous' file: '/tmp/Editor_xjbdm/LiveEditorEvaluationHelperEeditorId.m' workspace: {[1×1 struct]} within_file_path: ''
info2.workspace{1}
ans = struct with no fields.
this anonymous function has no captured variables
info3 = functions(h3)
info3 = struct with fields:
function: '@(x)sin(x+c)' type: 'anonymous' file: '/tmp/Editor_xjbdm/LiveEditorEvaluationHelperEeditorId.m' workspace: {[1×1 struct]} within_file_path: ''
info3.workspace{1}
ans = struct with fields:
c: 0
This anonymous function has captured variable 'c'

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Function Creation 的更多信息

产品


版本

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by