为什么在定义具有 0 个输出的 MATLAB containers.Map 子类方法时 "too many output arguments"?

Why "too many output arguments" when defining MATLAB containers.Map subclass method with 0 outputs?

我正在尝试通过子class 扩展 MATLAB containers.Map class 并添加一个具有 0 个输出的附加方法,但我遇到了 "too many output arguments" 错误执行方法时。这不是特定于新方法实现的——任何使用 0 输出扩展 containers.Map() 的附加方法都会产生此错误。

具体是执行时遇到的错误,

obj = Containers();
obj.testfun();

对于下面的class定义,

classdef Containers < handle & containers.Map
    methods       
        % Test function to display keys.
        function testfun(obj)
            obj.keys(); % dumby thing to execute with incoming object.
            disp('it works!');
        end
    end
end

然而,如果我们稍微修改它以输出至少一个参数,

classdef Containers < handle & containers.Map
    methods       
        % Test function to display keys.
        function dumby = testfun(obj)
            obj.keys();
            disp('it works!')
            dumby = 1;
        end
    end
end

它将正确执行。该错误似乎特别发生在 subclassing containers.Map 时。如果重要的话,我正在使用 MATLAB R2014b。关于如何解决这个问题有什么建议吗?

不要尝试子class containers.Map。这只是我的意见,但 MathWorks 应该做到了 Sealed 所以你做不到。

这里发生的事情是,当您键入 a.b、或 a(b)a{b} 时,它会转换为对方法 subsref 的调用。所有对象都有那个方法。有关 MATLAB 如何调用 subsref 的更多详细信息,请参阅 doc subsref,但请注意 - 它非常复杂。

现在,如果您想自定义 class 的行为,您可以通过提供自己的实现来重载 subsrefcontainers.Map 这样做,因为它需要支持按键索引,这对于其他 MATLAB classes 来说并不典型。

我无法准确告诉您 subsref for containers.Map 是如何实现的,因为它是内置的 class,所以我看不到代码。但我猜,从你在这里看到的行为来看,它在某些时候试图确定 .testfun() 是对方法 testfun 的调用还是 属性 testfun,或字段 testfun,或其他东西,它正在做的事情之一是查看是否使用输出参数调用它并相应地更改其行为。

这是一个很好的例子,说明在不知道(并可能修改)其内部结构的情况下,您无法真正地子class 对象,这就是为什么我建议 MathWorks 最好将此 Sealed 以防止您尝试。在任何情况下,如果没有一些解决方法(即为您的 Containers class 为了让它按照你想要的方式工作)和一些逆向工程(即二次猜测 containers.Mapsubsref 方法的内部结构)。

相反,您可以尝试使用适配器模式,通过创建您自己的 class 并将 containers.Map 作为私有(可能隐藏)属性,然后实现方法和属性只需将它们的参数和输出传递给底层 containers.Map。最后,也实现你自己的方法。