为什么我不能对重载subsref的类使用内置函数? [英] Why can't I use builtin for classes that overload subsref?
问题描述
我只想为特定类重载一种类型的subsref调用(()"类型),而将其他任何调用都保留给Matlab的内置subsref-特别是,我希望Matlab通过以下方式处理属性/方法访问这 '.'类型.但是,当subsref在类中重载时,Matlab的"builtin"功能似乎无法正常工作.
I would like to overload only one type of subsref calls (the '()' type) for a particular class and leave any other calls to Matlab's built in subsref -- specifically, I want Matlab to handle property/method access via the '.' type. But, it seems like Matlab's 'builtin' function doesn't work when subsref is overloaded in a class.
考虑此类:
classdef TestBuiltIn
properties
testprop = 'This is the built in method';
end
methods
function v = subsref(this, s)
disp('This is the overloaded method');
end
end
end
要使用重载的subsref方法,请执行以下操作:
To use the overloaded subsref method, I do this:
t = TestBuiltIn;
t.testprop
>> This is the overloaded method
这是预期的.但是现在我想调用Matlab的内置subsref方法.为了确保我做的正确,首先我尝试对struct进行类似的调用:
That's as expected. But now I want to call Matlab's built in subsref method. To make sure I'm doing things right, first I try out a similar call on a struct:
x.testprop = 'Accessed correctly';
s.type = '.';
s.subs = 'testprop';
builtin('subsref', x, s)
>> Accessed correctly
这也是预期的.但是,当我在TestBuiltIn上尝试相同的方法时:
That's as expected as well. But, when I try the same method on TestBuiltIn:
builtin('subsref', t, s)
>> This is the overloaded method
... Matlab调用重载方法,而不是内置方法.当我要求Matlab调用 builtin 方法时,为什么Matlab调用 overloaded 方法?
...Matlab calls the overloaded method rather than the built in method. Why does Matlab call the overloaded method when I requested that it call the builtin method?
更新: 响应@Andrew Janke的回答,该解决方案几乎可行,但效果不尽人意.考虑这个课程:
UPDATE: In response to @Andrew Janke's answer, that solution almost works but doesn't quite. Consider this class:
classdef TestIndexing
properties
prop1
child
end
methods
function this = TestIndexing(n)
if nargin==0
n = 1;
end
this.prop1 = n;
if n<2
this.child = TestIndexing(n+1);
else
this.child = ['child on instance ' num2str(n)];
end
end
function v = subsref(this, s)
if strcmp(s(1).type, '()')
v = 'overloaded method';
else
v = builtin('subsref', this, s);
end
end
end
end
所有这些工作:
t = TestIndexing;
t(1)
>> overloaded method
t.prop1
>> 1
t.child
>> [TestIndexing instance]
t.child.prop1
>> 2
但这是行不通的;它为子项使用内置的subsref,而不是重载的subsref:
But this doesn't work; it uses the built in subsref for the child rather than the overloaded subsref:
t.child(1)
>> [TestIndexing instance]
请注意,上述行为与这两种行为均不一致(符合预期):
Note that the above behavior is inconsistent with both of these behaviors (which are as expected):
tc = t.child;
tc(1)
>> overloaded method
x.child = t.child;
x.child(1)
>> overloaded method
推荐答案
可能是IIRC.要更改()
而不是{}
和'.',请编写您的subsref
方法,以将其他情况从重载的子引用中传递到内置的子引用中,而不是尝试从外部显式调用内置的内容.>
It's possible, IIRC. To change ()
but not {}
and '.', write your subsref
method to pass those other cases along to the builtin subsref from within your overloaded subsref, instead of trying to explicitly call the builtin from outside.
function B = subsref(A, S)
% Handle the first indexing on your obj itself
switch S(1).type
case '()'
B = % ... do your custom "()" behavior ...
otherwise
% Enable normal "." and "{}" behavior
B = builtin('subsref', A, S(1))
end
end
% Handle "chaining" (not sure this part is fully correct; it is tricky)
orig_B = B; % hold on to a copy for debugging purposes
if numel(S) > 1
B = subsref(B, S(2:end)); % regular call, not "builtin", to support overrides
end
end
(如果builtin
调用不起作用,则可以直接使用直接使用.
和{}
的情况,因为在类定义中忽略了subsref
重载.)
(And if that builtin
call doesn't work, you can just put in cases that use .
and {}
directly, because the subsref
overload is ignored inside the class definition.)
要使其完全起作用,您可能需要将B更改为varargout,并在()"情况下添加链接行为.
To make it fully functional, you may need to change B to a varargout, and add chaining behavior in to the "()" case.
这篇关于为什么我不能对重载subsref的类使用内置函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!