下面的函数会给你你想要的 - 子类名称,它是在调用(继承的)静态超类方法时使用的。只是把它的父类方法里像你将任何正常功能:
className = getStaticCallingClassName();
它所确实手柄:
- 无论何时编程方式(通过正在运行的脚本/功能,即在调用方法的情况下),以及从命令窗口调用的时间。
- 任意嵌套的软件包名称(即位于以
+
为前缀的目录中的类)。
它所不手柄:
- 不工作,如果静态方法被称为在非静态的情况下,即对对象实例。但是你不应该使用这样的语法。如果我们可以递归地使用
evalin
和'caller'
工作区,但这种方式不可行。
这个想法背后的简单解释:由dbstack
生成的堆栈跟踪中的第二项对应于超类,我们可以使用它来提取静态方法名称。接下来的步骤取决于:
- 如果方法调用编程,第三堆栈条目将指向我们的父脚本/功能,我们需要阅读,例如一条线使用
dbtype
。剩下要做的就是根据方法名称使用regexp
提取子类名称。
- 如果从命令窗口调用该方法,我们查询最后一个命令并将其用作正则表达式的输入。
请注意,即使堆栈有3个或更多条目,也不表示该方法是以编程方式调用的。例如,如果我们停在某处的断点处并从命令窗口调用该方法,则堆栈跟踪将很长,但基于来自第三个堆栈跟踪条目的行的regexp
不会给我们答案。在这种情况下,我们回到命令窗口的方法。
警告:它严重依赖未记录的功能,并可能在任何功能版本中崩溃。在Matlab 2015b上测试,但也应该适用于大多数以前的版本。有人可能会说它很脏,但它运行得很好,而且它是我意识到实现这种行为的唯一方法。
function [className, fullPath] = getStaticCallingClassName()
ST = dbstack('-completenames');
% First one is getStaticCallingClassName, second one is the superclass
methodName = char(regexp(ST(2).name, '[^\.]([^.]*)$', 'match'));
% matches string (combination of alphanumeric/underscore/dot characters) preceeding the given method call.
pattern = sprintf('[\\w.-]*(?=.%s)', methodName);
% If the parent called static method programmatically, we should be able to find it via the next (third) stack trace
if length(ST) > 2
command = evalc('dbtype(ST(3).file, num2str(ST(3).line))');
className = char(regexp(command, pattern, 'match'));
else % was likely called from command window. Long stack trace means that we're simply waiting in a breakpoint somewhere
className = []; % go straight to command window approach
end
if isempty(className) % means that static method was called directly from command window
javaHistory = com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory();
command = char(javaHistory(end));
className = char(regexp(command, pattern, 'match'));
end
fullPath = which(className);
end
你能展示你的一个子类是什么样的吗?我无法按照您设置的方式创建与您的超类一起工作的子类。 – Suever
您可以通过检查堆栈来获取它。但我认为最好将实例或类名传递给此方法。 – Navan
MATLAB中没有迟到的静态绑定。 dbstack可能是你最好的选择。 – siliconwafer