重载时如何强制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 【问题描述】:假设我有一个 X
类 MyClass
的对象。 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还是会尝试调用类方法,最后报错,因为compute2
在MyClass
中没有定义。 .
实际上如果你将常规函数重命名为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调用常规函数而不是类方法?的主要内容,如果未能解决你的问题,请参考以下文章