为什么我不能将内置用于重载subsref的类?

Ben*_*Ben 6 oop matlab overriding built-in

我想为特定类重载一种类型的subsref调用('(')类型),并保留对Matlab内置subsref的任何其他调用 - 具体来说,我希望Matlab通过'来处理属性/方法访问. " 类型.但是,当在类中重载subsref时,似乎Matlab的"内置"函数不起作用.

考虑这个课程:

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
Run Code Online (Sandbox Code Playgroud)

要使用重载的subsref方法,我这样做:

t = TestBuiltIn;
t.testprop
    >> This is the overloaded method
Run Code Online (Sandbox Code Playgroud)

这是预期的.但现在我想调用Matlab的内置subsref方法.为了确保我做得对,首先我尝试对结构进行类似的调用:

x.testprop = 'Accessed correctly';
s.type = '.';
s.subs = 'testprop';
builtin('subsref', x, s)
    >> Accessed correctly
Run Code Online (Sandbox Code Playgroud)

这也是预期的.但是,当我在TestBuiltIn上尝试相同的方法时:

builtin('subsref', t, s)
    >> This is the overloaded method
Run Code Online (Sandbox Code Playgroud)

... Matlab调用重载方法而不是内置方法.当我请求它调用内置方法时,为什么Matlab会调用重载方法?

更新:回应@Andrew Janke的回答,该解决方案几乎可行,但并不完全.考虑这个课程:

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
Run Code Online (Sandbox Code Playgroud)

所有这些都有效:

t = TestIndexing;
t(1)
    >> overloaded method
t.prop1
    >> 1
t.child
    >> [TestIndexing instance]
t.child.prop1
    >> 2
Run Code Online (Sandbox Code Playgroud)

但这不起作用; 它使用内置子参数为子而不是重载subsref:

t.child(1)
    >> [TestIndexing instance]
Run Code Online (Sandbox Code Playgroud)

请注意,上述行为与这两种行为(正如预期的那样)不一致:

tc = t.child;
tc(1)
    >> overloaded method

x.child = t.child;
x.child(1)
    >> overloaded method
Run Code Online (Sandbox Code Playgroud)

And*_*nke 4

这是有可能的,IIRC。要更改()但不{}更改 '.',请编写subsref方法以将这些其他情况从重载的子引用中传递到内置子引用,而不是尝试从外部显式调用内置子引用。

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
Run Code Online (Sandbox Code Playgroud)

(如果该builtin调用不起作用,您可以直接放入使用.和 的情况{},因为subsref重载在类定义中被忽略。)

为了使其功能齐全,您可能需要将 B 更改为 varargout,并将链接行为添加到“()”情况中。