重载时如何强制matlab调用常规函数而不是类方法?

Posted

技术标签:

【中文标题】重载时如何强制matlab调用常规函数而不是类方法?【英文标题】:How to force matlab to call a regular function rather than class method when they are overloaded? 【发布时间】:2013-07-08 17:29:48 【问题描述】:

假设我有一个 XMyClass 的对象。 MyClass有一个方法compute,当我调用U = compute(X,...)时,matlab会自动调用类方法。但是,我真正想要的是调用另一个也称为compute 的函数,其参数以MyClass 对象开头。如何强制 matlab 调用这个常规函数而不是进入类方法?

【问题讨论】:

为什么两个版本都不是成员方法?您还可以使外部函数成为类的静态方法,这样它的调用方式就不同了:MyClass.compute(x)compute(x) 【参考方案1】:

如果不对函数的名称或位置进行一些更改,就无法做到这一点。如果你检查Matlab's function precedence order,方法总是在正常的外部函数之前运行。您唯一可行的选择是:

    更改函数名称。 将函数体移动到调用函数的同一脚本(上面列表中的第 4 项) 将函数的 .m 文件移动到与脚本文件位于同一文件夹中的名为 private 的文件夹中(列表中的第 5 项)

更新

虽然对于小型项目不太实用,但您可能还想查看packaging your functions。可以在this SO post 找到一个很好的讨论。

【讨论】:

问题是,即使我把函数名改成compute2,matlab还是会尝试调用类方法,最后报错,因为compute2MyClass中没有定义。 . 实际上如果你将常规函数重命名为compute2 它将被正确调用(我只是在R2013a中尝试过) @OneZero 请记住,您需要更改函数名和包含该函数的文件名。因此,例如,您将在文件 compute2.m 中得到 function x = compute2(obj)【参考方案2】:

如果您的 compute 恰好是 MATLAB 内置函数,您可以使用

builtin('compute', ...)

否则,没有办法——请参阅 Bee 的回答。

【讨论】:

好点。我只是假设因为他的compute 函数接受自定义对象作为第一个参数,它不是内置函数。 @Bee:是的。 OP 很可能没有处理内置函数。但其他人可能:p【参考方案3】:

如果您迫切需要这个,那么您可以执行以下操作。我强烈建议您不要这样做,并坚持 Bee 的回答。然而,有时一个人别无选择......

这个想法是将您的实例包装在另一个类中,这样 MATLAB 的函数调度就不会看到 compute 方法。但是,对于您的 compute 函数,包装的实例必须与原始实例相同。在某些情况下很难做到这一点,但通常以下内容就足够了:

classdef Wrapper

    properties (Access = 'private', Hidden = true)
        core = [];
    end

    methods

        function this = Wrapper(core)
            this.core = core;
        end

        function varargout = subsref(this, S)
            if nargout > 0
                varargout = cell(1, nargout);
                [varargout:] = subsref(this.core, S);
            else
                subsref(this.core, S);
            end
        end

    end

end

这个类包装了另一个类的实例,并将所有读取权限委托给包装的实例。

例如,如果您有一个名为 TestClass.m 的文件:

classdef TestClass

    properties
        name = '';
    end

    methods
        function this = TestClass(name)
            this.name = name;
        end

        function compute(this)
            fprintf('Instance method! My name is "%s".\n', this.name);
        end
    end

end

还有一个函数compute.m

function compute(x)
    fprintf('Regular function! My name is "%s".\n', x.name);
end

然后它是这样工作的:

>> t = TestClass('t');
>> s = struct('name', 's');
>> compute(t)
Instance method! My name is "t".
>> compute(s)
Regular function! My name is "s".
>> w = Wrapper(t);
>> compute(w)
Regular function! My name is "t".

根据compute 函数对您的实例的作用,您可能需要向Wrapper 添加更多“特殊”函数(例如subsasgn)。另请注意,如果 compute 执行一些元类魔法,这将中断。

【讨论】:

最后一个doStuff(w) 应该是compute(w)。 +1 解决方法,但我也不建议在实际代码中使用它:) @Amro:谢谢,已修复。那是我试错代码的剩余部分。

以上是关于重载时如何强制matlab调用常规函数而不是类方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决使用文字 0 和指针调用重载函数的歧义

通过函数名后加const重载的函数如何区分调用

c++ 虚函数 如何调父类 而非子类

Python面向对象运算符重载

如何从同一个类中的另一个构造函数调用抽象类的构造函数(方法重载)[重复]

函数对象