我想访问调用抽象超类中实现的静态方法的具体类的类名。
这是抽象超类的代码(部分):
classdef (Abstract) AbstractJobProcessor < handle
properties (Abstract, Constant)
VERSION_MAJOR;
VERSION_MINOR;
LAST_MODIFIED;
end
...
methods (Static)
function res = getVersionMajor;
res = AbstractJobProcessor.VERSION_MAJOR;
end
function res = getVersionMinor
res = AbstractJobProcessor.VERSION_MINOR;
end
function res = getVersionInfo
res = sprintf('**CLASSNAME**: v%d.%02d (last modified: %s)',...
AbstractJobProcessor.VERSION_MAJOR,...
AbstractJobProcessor.VERSION_MINOR,...
AbstractJobProcessor.LAST_MODIFIED);
end
end
...
基本上,我想访问具体子类的类名,并在方法
getVersionInfo
中使用它来代替字符串**CLASSNAME**
。返回类的元信息的所有方法(我在文档中找到)都需要引用类的实例(例如
mc = metaclass(object)
)。 最佳答案
下面的函数将为您提供所需的子类名称,该名称在调用(继承的)静态超类方法时使用只要在超类方法中调用它,就像调用任何普通函数一样:
className = getStaticCallingClassName();
它处理的是什么:
方法以编程方式调用(即由正在运行的脚本/函数调用)的情况,以及从命令窗口调用它的情况。
任意嵌套的包名称(即位于前缀为
+
的目录中的类)。它不能处理的:
如果在非静态上下文(即对象实例)中调用静态方法,则不起作用但是无论如何你不应该使用这样的语法如果我们能够递归地将
evalin
与'caller'
工作区一起使用,这是可能的,但它不是这样工作的。这个想法背后的一个简单解释是:由
dbstack
生成的堆栈跟踪中的第二个条目将对应于超类,我们可以使用它来提取静态方法名下一步取决于:如果以编程方式调用该方法,则第三个堆栈条目将指向需要读取的父脚本/函数中的一行,例如使用
dbtype
剩下要做的就是根据方法名使用regexp
提取子类名称。如果从命令窗口调用该方法,我们将查询最后一个命令并将其用作正则表达式的输入。
注意,即使stack有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