我有一个带有一些辅助函数的目录,应放在一个包中。第一步显然是将目录命名为+mypackage\
,因此我可以使用mypackage.somefunction
调用函数。问题是,一些函数依赖于彼此,显然MATLAB要求包函数通过显式声明包名来调用同一个包中的函数,所以我必须重写所有函数调用。更糟糕的是,如果我决定重命名包,所有函数调用也必须重写。当cd
名称以+
开头时,这些函数甚至不再正常工作。
是否有比重写更轻松的解决方案? 或者至少是像 import this.*
这样的自我引用的东西,以方便将来的包重命名?
编辑我注意到类和静态方法也是如此,这就是我将自引用部分放入this separate question的原因。
答案 0 :(得分:15)
事实上,我不知道你应该经常重命名你的包裹。在我看来,package in MATLAB背后的整个想法是将一组相关的函数和类组织成一个集合,您可以轻松地使用或分发为“工具箱”,而不必担心名称冲突。 / p>
因此,将函数和类放入包中就像一个 final 步骤,您可以执行这些步骤来制作精美的工具集,因此您真的没有太多理由重命名您的包。此外,您只需要将包名称添加到包函数调用之后。
...(暂停思考,如果我建议的是一个好主意;))...
但是,如果您确实想要避免必须通过您的包并使用新的包名称添加函数调用,一种方法是使用函数mfilename
来获取当前运行的包函数的完整文件路径,解析路径字符串以查找父包目录(以“+”开头),然后将结果传递给import
函数以导入父包。您甚至可以将这些步骤放在单独的函数packagename
中(要求您还使用函数evalin
):
function name = packagename
% Get full path of calling function:
callerPath = evalin('caller', 'mfilename(''fullpath'')');
% Parse the path string to get package directories:
name = regexp(callerPath, '\+(\w)+', 'tokens');
% Format the output:
name = strcat([name{:}], [repmat({'.'}, 1, numel(name)-1) {''}]);
name = [name{:}];
end
然后您可以将它放在包函数的最开头,以自动将它们包含在父包命名空间中:
import([packagename '.*']);
这是个好主意吗?好吧,如果你每次调用一个包函数,那么我不确定计算的影响是什么。此外,如果您将包嵌套在包中,您将从packagename
获得如下所示的输出:
'mainpack.subpack.subsubpack'
对import
的调用只包含直接父包subsubpack
。如果您还想包含其他父包,则必须从上面的字符串中依次删除最后一个包并导入该字符串的其余部分。
简而言之,这不是一个非常干净的解决方案,但它 可以使您的包更容易以这种方式重命名。但是,我仍然建议最好将创建一个包作为创建核心工具集的过程中的最后一步,在这种情况下,重命名应该是一个不太可能的场景,并且使用包名称预先包装函数调用只需要做一次。
答案 1 :(得分:3)
我一直在探索相同问题的答案,并且我发现将包与私人文件夹组合可以允许使用大部分或全部代码而无需修改。
说你有
+mypackage\intfc1.m
+mypackage\intfc2.m
+mypackage\private\foo1.m
+mypackage\private\foo2.m
+mypackage\private\foo3.m
然后来自intfc1
,foo1
,foo2
和foo3
都可以在没有任何包限定符或导入语句的情况下到达,foo1
,{{1并且foo2
也可以在没有任何包限定符或import语句的情况下相互调用。如果foo3
,foo1
或foo2
需要调用foo3
或intfc1
,那么需要将其限定为intfc2
或导入声明。< / p>
如果您拥有大量相互依赖的函数和少量入口点,则可以减少添加限定符或导入语句的负担。
为了更进一步,您可以在包级别创建与私有函数同名的新包装函数
mypackage.intfc1
例如+mypackage\foo1.m <--- new interface layer wraps private foo1
+mypackage\private\foo1.m <--- original function
可能是:
+mypackage\foo1.m
这样,与上面的function answer = foo1(some_parameter)
answer = foo1(some_parameter); % calls private function, not itself
end
示例不同,所有私有代码都可以无需修改即可运行。特别是在调用任何其他函数时不需要包限定符,无论它是否由包级别的包装器公开。
使用此配置,包括包级别包装器在内的所有函数都无视包名,因此重命名包只不过是重命名文件夹。