Matlab中的類定義 classdef

2021-06-27 11:21:52 字數 4618 閱讀 6481

matlab也可以寫物件導向的**,首先表現在可以定義類,以及可以繼承,

使用類(class)有很多好處,其中乙個重要的好處便是解決變數名衝突和讓函式、物件的結構清晰。class的static function可以在不定義類的例項直接呼叫類的成員函式,比如定義

classdef tools < handle

methods (static = true)

function a = test(b, c)

a = b + c;

endend

end

然後可以直接通過

a = tools.test(b, c);
呼叫函式。

classdel是定義類名,後面的《是表示繼承,matlab允許多重繼承,繼承自handle類,handle類定義了很多關於object的處理函式,例如addlistener以及notify還有delete等對物件的函式,是乙個抽象類,不能例項化,具體可以看一下參考文獻。

類的方法是放在methods ...end裡面。

下面是乙個稍微複雜的類的定義

classdef tensiledata

properties

material = 'carbon steel';

samplenumber = 0;

stress

strain

endproperties (dependent)

modulus

endmethods

function td = tensiledata(material,samplenum,stress,strain)

if nargin > 0

td.material = material;

td.samplenumber = samplenum;

td.stress = stress;

td.strain = strain;

endend % tensiledata

endmethods

function obj = set.material(obj,material)

if ~(strcmpi(material,'aluminum') ||...

strcmpi(material,'stainless steel') ||...

strcmpi(material,'carbon steel'))

error('material must be aluminum, stainless steel, or carbon steel')

endobj.material = material;

end % material set function

function modulus = get.modulus(obj)

ind = find(obj.strain > 0); % find nonzero strain

modulus = mean(obj.stress(ind)./obj.strain(ind));

end % modulus get function

function obj = set.modulus(obj,~)

fprintf('%s%d\n','modulus is: ',obj.modulus)

error('you cannot set modulus explicitly');

endfunction disp(td)

fprintf(1,'material: %s\nsample number: %g\nmodulus: %1.5g\n',...

td.material,td.samplenumber,td.modulus);

end % disp

function plot(td,varargin)

plot(td.strain,td.stress,varargin)

title(['stress/strain plot for sample ',num2str(td.samplenumber)])

xlabel('strain %')

ylabel('stress (psi)')

end % plot

endmethods (access = 'private') % access by class members only

function m = calcmodulus(td)

% over-simplified calculation of elastic modulus

ind = find(td.strain > 0); % find nonzero strain

m = mean(td.stress(ind)./td.strain(ind));

end % calcmodulus

endend % classdef

在上述**中,

classdef tensiledata

...end

是定義乙個tensiledata類。**:

properties

material = 'carbon steel';

samplenumber = 0;

stress

strain

end是定義這個類的屬性,也就是c++中類的成員變數。但是和c++不同的是,matlab中的類定義還有乙個比較特別的地方的,就是定義依賴屬性,如下述**:

properties (dependent)

modulus

end

這表示modulus這個屬性是個依賴屬性,它的值是通過其他屬性計算得到的,其中dependent的預設屬性值為true。

它的值是通過下面函式實現的:

% modulus get function

function modulus = get.modulus(obj)

ind = find(obj.strain > 0); % find nonzero strain

modulus = mean(obj.stress(ind)./obj.strain(ind));

end

類的方法(函式)的定義是以methods ... end的的形式出現的。如下面的類方法的定義:

methods

function td = tensiledata(material,samplenum,stress,strain)

if nargin > 0

td.material = material;

td.samplenumber = samplenum;

td.stress = stress;

td.strain = strain;

endend 

end

該函式塊定義了tensiledata建構函式方法。上述**中的最後乙個方法 methods (access = 'private')

中的access = 'private'表示該方法僅能被類本身訪問和修改,是個私有成員方法。其中屬性access又可分為

setaccess和getaccess,屬性值和access相同。

封裝後的函式多次呼叫會話費相當長的時間

所以到底該不該封裝,還需取決於實際情況,如果函式本身特別簡單,並且會被迴圈呼叫,最好還是通過m檔案函式的形式。之前mit大牛給出了更多地建議

雖然for-loop的速度有了很大改善,vectorization(向量化)仍舊是改善效率的重要途徑,尤其是在能把運算改寫成矩陣乘法的情況下,改善尤為顯著。

在不少情況下,for-loop本身已經不構成太大問題,尤其是當迴圈體本身需要較多的計算的時候。這個時候,改善概率的關鍵在於改善迴圈體本身而不是去掉for-loop。

matlab的函式呼叫過程(非built-in function)有顯著開銷,因此,在效率要求較高的**中,應該盡可能採用扁平的呼叫結構,也就是在保持**清晰和可維護的情況下,盡量直接寫表示式和利用built-in function,避免不必要的自定義函式呼叫過程。在次數很多的迴圈體內(包括在cellfun, arrayfun等實際上蘊含迴圈的函式)形成長呼叫鏈,會帶來很大的開銷。

在呼叫函式時,首選built-in function,然後是普通的m-file函式,然後才是function handle或者anonymous function。在使用function handle或者anonymous function作為引數傳遞時,如果該函式被呼叫多次,最好先用乙個變數接住,再傳入該變數。這樣,可以有效避免重複的解析過程。

在可能的情況下,使用numeric array或者struct array,它們的效率大幅度高於cell array(幾十倍甚至更多)。對於struct,盡可能使用普通的域(字段,field)訪問方式,在非效率關鍵,執行次數較少,而靈活性要求較高的**中,可以考慮使用動態名稱的域訪問。

雖然object-oriented從軟體工程的角度更為優勝,而且object的使用很多時候很方便,但是matlab目前對於oo的實現效率很低,在效率關鍵的**中應該慎用objects。

如果需要設計類,應該盡可能採用普通的property,而避免靈活但是效率很低的dependent property。如非確實必要,避免過載subsref和subsasgn函式,因為這會全面接管對於object的介面呼叫,往往會帶來非常巨大的開銷(成千上萬倍的減慢),甚至使得本來幾乎不是問題的**成為效能瓶頸。

參考文獻:

Matlab 中類的定義

2.2 properties 塊 2.3 methods 塊 2.4 events 塊 2.5 enumeration 類 在 matlab 中定義乙個名為 classname 類,需要在類名之前用classdef關鍵字來宣告,並以end結束類的定義。classdef語句之前除了空行和注釋不能有其它...

matlab中的類定義classdef

classdef attribute value classname superclass end定義多個attribute時,在括號中用逗號隔開。name class description hidden logical 在matlab輸出中不顯示該類 inferiorclasses cell,即...

Python中怎樣初始化乙個類類class?

1 12 1 fp樹的類定義 2class treenode 3def init self,namevalue,numoccur,parentnode 4 self.name namevalue 節點的名字 5 self.count numoccur 出現次數 6 self.nodelink non...