2016-03-03 58 views
3

我想访问调用在抽象超类中实现的静态方法的具体类的类名称。抽象类的静态方法中的类名称

这是代码的抽象superclasss的(部分):

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 
... 

基本上,我想访问具体子类的类名和代替串**CLASSNAME**的使用它的方法getVersionInfo

所有返回有关某个类的元信息的方法(我在文档中找到的)都需要引用该类的实例(例如,mc = metaclass(object))。

+0

你能展示你的一个子类是什么样的吗?我无法按照您设置的方式创建与您的超类一起工作的子类。 – Suever

+0

您可以通过检查堆栈来获取它。但我认为最好将实例或类名传递给此方法。 – Navan

+1

MATLAB中没有迟到的静态绑定。 dbstack可能是你最好的选择。 – siliconwafer

回答

1

下面的函数会给你你想要的 - 子类名称,它是在调用(继承的)静态超类方法时使用的。只是把它的父类方法里像你将任何正常功能:

className = getStaticCallingClassName(); 

它所确实手柄:

  • 无论何时编程方式(通过正在运行的脚本/功能,即在调用方法的情况下),以及从命令窗口调用的时间。
  • 任意嵌套的软件包名称(即位于以+为前缀的目录中的类)。

它所手柄:

  • 不工作,如果静态方法被称为在非静态的情况下,即对对象实例。但是你不应该使用这样的语法。如果我们可以递归地使用evalin'caller'工作区,但这种方式不可行。

这个想法背后的简单解释:由dbstack生成的堆栈跟踪中的第二项对应于超类,我们可以使用它来提取静态方法名称。接下来的步骤取决于:

  1. 如果方法调用编程,第三堆栈条目将指向我们的父脚本/功能,我们需要阅读,例如一条线使用dbtype。剩下要做的就是根据方法名称使用regexp提取子类名称。
  2. 如果从命令窗口调用该方法,我们查询最后一个命令并将其用作正则表达式的输入。

请注意,即使堆栈有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