Overloading subsrefs for class and using it from another method in the same class
3 ビュー (過去 30 日間)
古いコメントを表示
Take the following example:
classdef testClass < handle
properties (Access = private)
number
end
methods
function obj = testClass(value)
obj.number = value;
end
function varargout = subsref(obj, S)
% Overload the "." operator for get access
switch S(1).type
case '.'
if strcmp(S(1).subs, 'number')
[varargout{1}] = obj.number+1; % We always add 1 to number
return;
elseif any(strcmp(S(1).subs, methods(obj)))
% If the field name is a method of the object,
% call the method using feval
if numel(S) > 1 && strcmp(S(2).type, '()')
% If there are arguments for the method, pass them
[varargout{1:nargout}] = feval(S(1).subs, obj, S(2).subs{:});
else
% Otherwise, just call the method
[varargout{1:nargout}] = feval(S(1).subs, obj);
end
return;
end
end
error('Not handled');
end
function print_number(obj)
num = obj.number; % Should call subsref?
fprintf('%g\n', num);
end
end
end
And I run this:
A = testClass(3);
A.number; % This returns 4, as expected.
However:
A.print_number() % This prints "3".
How come A.print_number() does not print 4?
How do I code my subsref so that it can work properly when calling from a method of the same class?
I would like to be able to do A.number within testClass methods and have it call the overloaded subsref without having to define set.number or get.number methods. In my real use case, testClass would contain a containers.Map(). The subsref would over loaded so that testClass.key1 would return the value of the containers.Map() with a key of "key1".
0 件のコメント
採用された回答
Matt J
2024 年 4 月 2 日
編集済み: Matt J
2024 年 4 月 2 日
As an alternative to subsref or set/get, you could look at RedefinesDot, but I find that the newer, modular indexing can have surprising behavior, discussed extensively at,
4 件のコメント
Matt J
2024 年 4 月 4 日
Using RedefinesDot works for me. But your code only works R2022b or later.
That is strange. I implemented essentially the same thing in R2021b here with no difficulties:
その他の回答 (1 件)
Matt J
2024 年 4 月 2 日
編集済み: Matt J
2024 年 4 月 2 日
No, subsref is only called by indexing operations invoked outside the classdef. This design decision was to avoid triggering recursions when indexing operations are done inside the subsref method itself. For example, you would not want this instance of obj.number to call subsref,
[varargout{1}] = obj.number+1;
as that would cause an infinite recursion. I'm not sure why such recursions couldn't have been blocked the same way they are blocked for set/get methods, but that's just the way it's always been.
I would like to be able to do A.number within testClass methods and have it call the overloaded subsref without having to define set.number or get.number methods.
I don't know why you think avoiding set and get methods is beneficial. Probably for different reasons, though, I would also not recommend set/get methods for number. I would instead recommend introducing a Dependent property:
classdef testClass < handle
properties (Access = private)
number
end
properties (Dependent)
Number
end
methods
function obj = testClass(value)
obj.number = value;
end
function val=get.Number(obj)
val=obj.number+1;
end
function print_number(obj)
num = obj.Number; % Should call subsref?
fprintf('%g\n', num);
end
end
end
4 件のコメント
Matt J
2024 年 4 月 3 日
編集済み: Matt J
2024 年 4 月 3 日
Can you prove that calling the overloaded subs* methods won't ever introduce recursion in those other class methods? That there aren't any circumstances where the subs* methods would call back to the same methods that called them?
Even if there is no way to make subsref recursion-proof, the same danger already exists with property set/get methods, as in the example below. So, there is already precedent for making the scope of overloaded indexing method-specific. According to my conversations with @James Lebak, this nonuniformity in the scope of overloaded indexing is something MathWorks is trying to move away from. I'm not sure what the drawbacks of such nonuniformity are seen to be.
classdef myclass
properties
prop
end
methods
function val=get.prop(obj)
val=subget(obj);
end
function val=subget(obj)
val=obj.prop;
end
end
end
参考
カテゴリ
Help Center および File Exchange で Subclass Definition についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!