我想访问调用抽象超类中实现的静态方法的具体类的类名。
这是抽象超类的代码(部分):
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)
)。
答案 0 :(得分:1)
下面的函数将为您提供所需的内容 - 在调用(继承的)静态超类方法时使用的子类名称。只需在您的超类方法中调用它,就像使用任何普通函数一样:
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
答案 1 :(得分:1)
这是解决方法。根据MATLAB文档:
如果使用空对象数组调用普通方法,则可以使用静态方法的两个方面。
例如,假设我们有一个基类:
classdef base
methods
function obj = base()
disp('constructor called')
end
function dispClassName(obj)
disp(['class name = ', class(obj)]);
end
end
end
和子类
classdef sub < base
end
现在调用方法如下(这不会调用任何构造函数):
>> base.empty.dispClassName
class name = base
>> sub.empty.dispClassName
class name = sub
一个真正的解决方案(我为MathWorks做了一个增强请求03315500)将扩展MATLAB语言的方法属性&#39; Class&#39;定义与调用类关联的方法(类似于Python @classmethod装饰器)。此类的方法将自动接收调用函数的元类作为第一个参数。有了这样的扩展,我们可以定义一个基类:
% Future MATLAB syntax extension
classdef base
methods(Class) % New method attribute ‘Class’
function dispClassName(cls) % implicit argument (meta.class)
disp(['class name = ' cls.Name ]);
end
end
end
和子类
classdef sub < base
end
并致电
>> base.dispClassName
class name = base
>> sub.dispClassName
class name = sub