【问题标题】:Matlab: Can't run class method as a normal function?Matlab:不能将类方法作为普通函数运行?
【发布时间】:2018-09-19 06:54:56
【问题描述】:

我定义了一个类cMyClass,其方法是@cMyClass 文件夹中的一个单独的m 文件SomeMethod.m。只要将SomeMethod 复制到文件夹@cMyClass 之外,我就可以将SomeMethod 作为普通函数(而不是方法)调用。但是,当当前工作目录是文件夹 @cMyClass 时,SomeMethod 无法识别(我提供了一个空结构作为参数来代替预期的主机对象)。在将文件夹更改为 @cMyClass 后,我尝试了 clear classesrehash,但它们没有帮助。

这会带走战术测试和故障排除的便利。我想知道这种行为是否真的被硬编码到 Matlab 中,还是我遗漏了什么?测试代码如下。

类定义@cMyClass/cMyClass.m

% @cMyClass/cMyClass.m
% --------------------
classdef cMyClass < handle
   methods
      SomeMethod(o)
   end % methods
end % classdef

@cMyClass/SomeMethod.m中的方法定义:

% @cMyClass/SomeMethod.m
% ----------------------
function SomeMethod(o)
'Hello world'
end % function

我成功地将SomeMethod作为类方法的常规调用:

>> oMyClass = cMyClass
oMyClass =
  cMyClass with no properties.
>> oMyClass.SomeMethod
ans =
Hello world

不幸的是,我未能从文件夹 @cMyClass 调用 SomeMethod 作为正常函数:

>> cd @cMyClass
>> clear all; clear classes
>> rehash
>> o=struct
o =
struct with no fields.
>> SomeMethod(o)
Undefined function or variable 'SomeMethod'.

但是,我成功地从@cMyClass 外部调用了SomeMethod。我使用 shell 将 SomeMethod.m 上一层复制到 @cMyClass/..(在 POSIX 路径表示法中),然后执行:

>> cd .. % Go to @cMyClass/..
>> clear all; clear classes
>> rehash
>> o=struct
o =
struct with no fields.
>> SomeMethod(o)
ans =
Hello world

当函数不驻留在以@ 开头的文件夹中时,另一个成功的例子是将@cMyClass 复制到not_cMyClass 并执行:

>> cd not_cMyClass
> clear all; clear classes
>> rehash
>> o=struct
o = 
struct with no fields.
>> SomeMethod(o)
ans =
Hello world

令人费解的是,当Matlab的当前工作目录为@cMyClass时,cMyClass不被识别为类,所以SomeMethod.m不应该被解释为方法文件:

>> cd ..\@cMyClass\
>> clear all
>> clear classes
>> rehash
>> c=cMyClass
Undefined function or variable 'cMyClass'. 

换句话说,人们会期望SomeMethod.m 被解释为一个普通的函数文件,就像它驻留在上面的not_cMyClass@cMyClass/.. 中时一样。

代替解决方案,我必须在文件夹 @cMyClass 之外维护 SomeMethod.m 的副本,并手动保持两个副本同步。人为错误成为一种危险。

请注意,由于我在 Microsoft Windows 机器上使用 Cygwin,/\ 都用作路径分隔符,具体取决于上下文。

请注意,使用 unix 的 ln -s 或通过在 @cMyClass/.. 中创建 Microsoft Windows 快捷方式来创建虚拟副本不起作用。 Matlab 不会将这些识别为 m 文件。

【问题讨论】:

  • 我们能看一下代码 sn-p 吗?你的描述很清楚,但这会让一切变得更容易。
  • 您可以在单独的文件夹中使用指向这些函数的符号链接。 (至少在 Mac 上)仅创建指向包含函数的文件夹的符号链接是行不通的,因为符号链接的 cd 将由 MATLAB 解析为原始路径。
  • 我在接近尾声时添加了进一步的评论,以描述我对软链接的不成功实验。我还发现无法将方法作为非方法函数调用的后果比我担心的要严重,并且在接近尾声时也进行了描述。
  • 糟糕。最后一句话是无效的,但我不能再删除它。 5 分钟窗口已过。
  • @user36800:听起来你有一个函数SomeMethod,你希望能够调用任何对象(不必以类名开头),但它也应该做一些处理cMyClass 的对象时情况略有不同(因此,为什么您希望它成为一种方法)?并且您只想维护该函数的一份副本?

标签: matlab class oop methods


【解决方案1】:

这是预期的行为。 MATLAB 根据参数的类型分派函数调用。如果obj 的类型为cMyClass,则将为func(obj) 调用函数cMyClass/func。如果没有,将调用不同的func。如果func 没有为obj 是任何类定义,并且在类目录之外没有func,则会出现错误。

无法使用func({}) 或类似的语法调用@cMyClass/func.m。如果您希望能够使用空对象调用此函数,则需要修改您的类,以便cMyClass(类构造函数)返回一个空对象。那你就可以func(cMyClass)了。

另一种选择是将func 设为static method。然后你可以称它为 wuth cMyClass.func

请注意,对于故障排除和调试,您仍然可以像设置任何其他功能一样设置断点和调试。实在看不出有必要用非法输入调用这样的函数……

【讨论】:

  • 我添加了示例代码来说明为什么人们期望 SomeMethod.m 被解释为一个普通的(非方法)函数,以及显示对 SomeMethod 的调用具有有效的作为非方法函数调用时的参数。
  • 顺便说一句,我有兴趣在方法的上下文之外调用该函数,因为我正在进行大规模重新编码,因此并非整个类中的所有代码在转换期间都是自洽的。但是,我仍然想编写一点代码,进行一点测试。
  • @user36800:这部分令人惊讶:“当Matlab的当前工作目录为@cMyClass时,cMyClass不被识别为一个类”。我以前没有注意到这一点。将类方法作为独立函数运行的问题是类方法中的代码被不同地解释。例如索引的工作方式不同,重载的索引运算符不会被调用。
  • 能够使用keyboard 将m 文件作为非方法函数调用以防止执行到达在方法调用上下文之外有问题的代码仍然很有用。否则,我最终会将 m 文件复制到其他地方,并确保我修改了正确的文件并保持两者同步。人为错误成为问题。
猜你喜欢
  • 1970-01-01
  • 2017-11-10
  • 2019-01-28
  • 2013-10-11
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
相关资源
最近更新 更多