2016-03-03 98 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