为什么我不能对重载subsref的类使用内置函数? [英] Why can't I use builtin for classes that overload subsref?

查看:109
本文介绍了为什么我不能对重载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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆