2011-06-23 92 views
15

有沒有辦法在MATLAB類中定義靜態成員變量?如何在MATLAB類中獲取靜態成員變量?

這不起作用:

classdef A 

    properties (Static) 
     m = 0; 
    end 
end 

它建議使用關鍵字「恆」,而不是「靜態」的,恆定的屬性不能被修改。我想要一個通用於類A的所有對象的變量,我希望能夠在類A的方法中修改該變量。

所以我需要的是一個私人靜態成員變量。有沒有辦法在MATLAB中獲得它?


發現了一種解決方法可以在靜態成員函數使用持久變量來完成

在這種情況下,您應該繼承基類中的所有類,如下所示。

classdef object < handle 

    properties (GetAccess = 'public', SetAccess = 'private') 
     id 
    end 

    methods (Access = 'protected') 
     function obj = object() 
      obj.id = object.increment(); 
     end 
    end 

    methods (Static, Access = 'private') 
     function result = increment() 
      persistent stamp; 
      if isempty(stamp) 
       stamp = 0; 
      end 
      stamp = stamp + uint32(1); 
      result = stamp; 
     end 
    end 
end 
+1

這並不意味着它AFAIK,但[持久](http://www.mathworks.com/help/techdoc/ref/persistent.html)工作? –

+1

是的,我在靜態成員函數中獲得了一個帶有持久變量的解決方法。 – Vahagn

+1

您應該將其作爲對此問題感興趣的其他人的回答 –

回答

15

你不能,它是由設計。你應該使用一個變量(在2011年應用於1980年的MATLAB技術)!

爲了完整起見,我應該提到,實際上2010年有一個沒有記錄的,可能不再支持static屬性修飾符。

有關背景看hereDave Foti答案,MATLAB OO組經理:

在MATLAB中,類可以定義常量 性質,但在其他 語言,如C的感覺不是「靜」 性質++ 。有測試 版本,試驗 「靜態」屬性和 未記錄的屬性仍然從 然後。但是,在未來的 MATLAB版本中,靜態屬性 未被記錄,不應使用,並且 可能會被刪除。 R2008a將其實現爲 作爲常量的同義詞,並且提供 超越 的常規 屬性的已記錄行爲。

不變屬性可能不會改變 從 中指定的初始值屬性聲明。有幾個原因是爲什麼MATLAB的工作原理是 。首先,MATLAB具有 長期規則,變量 總是優先於函數和類的名稱 , 賦值語句引入 變量(如果尚不存在)。因此,「A.B = C」形式的任何表達式都將引入一個新變量A,該變量是一個結構數組,其中包含一個值爲C的字段B的 。B = C」 可以指 類A的靜態屬性,那麼類A採取 先例在變量A和這 將是一個非常顯著 不相容與以前版本的MATLAB ,這將意味着一個 米-file含分配 聲明「AB = C」也有其 含義由一個名爲 MATLAB路徑上的某處類的介紹 改變。MATLAB程序員 總是能夠依靠賦值語句 引入變量 影子任何其他使用相同的名稱。

其次,我們發現靜態 數據很少用於其他類 ,除非作爲 類中的私人數據或作爲公共常量。例如,對幾個Java類庫的調查發現,所有公共的 靜態字段也是最終的。在 MATLAB中,常量屬性可以是 ,類似於Java中的「public final static」 字段。對於 類的內部數據,MATLAB已經擁有了持久性 變量,這些變量可以在私有或受保護方法的 內創建,或者 類私下使用的本地函數。 也有很好的理由避免MATLAB中的靜態數據,其中 可能。如果某個類具有靜態數據,則可能難以在多個應用程序 中使用相同的 類,因爲靜態數據可能是 應用程序之間的衝突源。在其他一些語言中,這不是一個問題,因爲 不同的應用程序分別是 編譯成 運行在 可執行文件不同的進程與不同的 類靜態數據的副本。在MATLAB中,經常有許多不同的 應用程序可能正在運行在 相同的進程和環境中,並且每個類都有一個 單一副本。

11

下面是在Matlab中創建靜態屬性的直接方法。這個實現和假設(但不可能;見Mikhail的答案)之間的唯一區別是真正的靜態屬性是設置成員變量的語法。

classdef StaticVarClass 
    methods (Static = true) 
     function val = staticVar(newval) 
      persistent currentval; 
      if nargin >= 1 
       currentval = newval; 
      end 
      val = currentval; 
     end 
    end 
end 

現在的靜態屬性staticVar中可以通過讀取:

StaticVarClass.staticVar 

...,並通過設置:

StaticVarClass.staticVar(newval); 

所以,舉例來說,這是從投料到產出對此功能的測試:

>> StaticVarClass.staticVar 
    ans = 
     [] 
>> StaticVarClass.staticVar('foobar') 
    ans = 
     foobar 
>> StaticVarClass.staticVar 
    ans = 
     foobar 
>> 

此方法對於您請求的私有靜態屬性也同樣適用,但演示代碼稍長一些。請注意,這不是一個句柄類(儘管它也可以很好地處理句柄類)。

classdef StaticVarClass 
    methods (Access = private, Static = true) 
     function val = staticVar(newval) 
      persistent currentval; 
      if nargin >= 1 
       currentval = newval; 
      end 
      val = currentval; 
     end 
    end 

    methods 
     function this = setStatic(this, newval) 
      StaticVarClass.staticVar(newval); 
     end 

     function v = getStatic(this) 
      v = StaticVarClass.staticVar; 
     end 
    end 
end 

...和測試:

>> x = StaticVarClass 
    x = 
     StaticVarClass with no properties. 
     Methods 
>> x.getStatic 
    ans = 
     [] 
>> x.setStatic('foobar') 
    ans = 
     StaticVarClass with no properties. 
     Methods 
>> x.getStatic 
    ans = 
     foobar 
>> 
0

(只是通知) 有(另一個?)的方式來創建MATLAB靜態類數據

假設你有一個「處理」類,它的名字是「汽車」 如果你想要的車類具有靜態數據,你可以構造另一個手柄類和汽車類拋成分使用,後一類可以作爲面向汽車類

classdef car<handle 
    properties 
     static_data:STATIC_DATA_HOLDER; 
    end 
end 

classdef STATIC_DATA_HOLDER<handle 
    properties 
     data 
    end 
end 

這樣,當一個靜態數據你創建一輛汽車的第一個實例類,則會創建一個STATIC_DATA_HOLDER實例,並在創建汽車類的第二個實例時使用之前創建的STATIC_DATA_HOLDER類。

這些代碼以「MATLAB 2013b」

0

另一個解決辦法要達到這樣的靜電性能測試是使用加載的類文件時,成員變量的初始化代碼只執行一次的事實。這意味着,如果你有一個像

classdef foo 
    properties 
     stuff = some_function() 
    end 
end 

然後some_function被調用的定義只有一次,如果返回的類類型的對象,這會被所有實例共享。我添加了一個簡單的實現,顯示瞭如何可以使用:

classdef ClassWithStaticMembers 
    properties 
     classvars = StaticVarContainer('foo', 0, 'bar', 2); 
     othervar 
    end 
    methods 
     function obj=ClassWithStaticMembers(var) 
      obj.othervar = var; 
     end 
    end 
end 

classdef StaticVarContainer < dynamicprops 
    methods 
     function obj=StaticVarContainer(varargin) 
      for i=1:2:numel(varargin) 
       obj.addprop(varargin{i}); 
       obj.(varargin{i}) = varargin{i+1}; 
      end 
     end 
    end 
end 

如果您運行此示例代碼

obj1 = ClassWithStaticMembers(3); 
obj2 = ClassWithStaticMembers(5); 
obj1.classvars.foo = [2,3]; 

obj1.othervar 
obj1.classvars 

obj2.othervar 
obj2.classvars 

,你會看到,classvars確實共享。我認爲這個解決方案比在函數中使用持久變量要好得多,因爲您可以隨意重複使用StaticVarContainer,它更易於使用,此外,您還可以直接在屬性部分查看靜態變量的初始化。

要獲得的結果,即期望在OP的問題(即,實施一個對象計數器)的共享屬性可以由Constant,以便它可以在不一個實例在手被引用:

classdef ClassWithCounter 
    properties (Constant) 
     static = StaticVarContainer('counter', 0); 
    end 
    methods 
     function obj=ClassWithCounter() 
      obj.static.counter = obj.static.counter + 1; 
     end 
    end 
end 

clear all 
obj1 = ClassWithCounter(); 
obj2 = ClassWithCounter(); 
obj3 = ClassWithCounter(); 

ClassWithCounter.static.counter 

請注意,Constant屬性僅意味着,例如obj1.static不能改變,但它不影響obj1.static.counter這是不恆定的,可以設置爲心的願望。