Matlab05 (431kB
Transkript
5. Programování 5.1 Skripty / funkce Programy v Matlabu se píší jako sled příkazů Matlabu do textového souboru, tento se potom spouští jediným příkazem, který odpovídá názvu daného souboru. Existují dva druhy programů: skripty a funkce • • Skripty pouze provádí sled příkazů Matlabu (nemají vstupní argumenty ani nic nevrací). Proměnné jsou uloženy ve společném (hlavním) workspacu. Funkce mohou mít argumenty a mohou vracet hodnotu. Proměnné jsou uloženy v lokálním workspacu. 5.2 Skripty Sdílí data s workspace a ostatními skripty. Většinou jednoduchý sled příkazů který by se jinak musel provádět několikrát. Př. % skript ktery namaluje sin a cos v rozmezi 0-2pi fi = 0:0.1:2*pi; sin_fi = sin(fi); cos_fi = cos(fi); plot(fi,sin_fi,fi,cos_fi); % skript ktery ceka na enter prikazem pause fi = 0:0.1:2*pi; sin_fi = sin(fi); cos_fi = cos(fi); plot(fi,sin_fi); pause plot(fi,cos_fi); Pozor, pracuje se s globálním workspace – pokud script přepíše některou proměnnou je už přepsaná na pořád. % script pokus1.m a = peaks(30); %script pokus2.m mesh(a); a = 10; pokud spustíme script pokus2.m dříve než pokus1.m bude hlášena chyba – proměnná a neexistuje a není možné z ní zobrazit povrch. Pokud spustíme pokus2.m dvakrát po sobě, bude při druhém spuštění zobrazen pouze 3D grid bez dat (a obsahuje pouze jednu skalární hodnotu). - 1/24 - Skripty mohou obsahovat příkazy řízení toku programu (podmínky, cykly, …) Př. % script na ukazku nekterych klicovych slov clear all; delka = 1000; x = 0 : 0.1 :delka; % cyklus for for i= 1:length(x) y(i) = x(i)*sqrt(x(i)); z(i) = x(i)*y(i); end % podminka if length(x) > 100 a = 'dlouha uloha'; plot(x,y); else a = 'kratka uloha'; plot(x,z); end %vypis hodnoty a 5.3 Řízení běhu programu 5.3.1 Podmínka if logicky_vyraz prikazy end př. if a <= 10 b = a * 5; end logické výrazy využívají aritmetických, relačních a logických operátorů. Rozšířený tvar podmínky if n < 0 % je-li n záporné, zobraz chybové hlášení disp('vstup musi byt kladny'); elseif rem(n,2) == 0 % je-li n kladne a sude, vydel ho dvema. A = n/2; else A = (n+1)/2; % je-li n kladne a liche, pricti jednicku a vydel dvema end - 2/24 - Příkaz switch – (obdoba case) switch vyraz % (skalar nebo retezec) case hodnota1 prikazy % provede se pokud vyraz odpovida hodnota1 case hodnota2 prikazy % provede se pokud vyraz odpovida hodnota2 . . . otherwise prikazy % provede se ve vsech ostatnich pripadech end Př. switch vstup case -1 disp('minus jedna'); case 0 disp('nula'); case 1 disp('plus jedna'); otherwise disp('jina hodnota'); end 5.3.2 Cyklus Cyklus FOR použijeme pokud známe dopředu počet kroků které se mají provést. Cykly je možné vnořovat do sebe. for index = zacatek:inkrement:konec prikazy end Př. for m = 1:5 for n = 1:100 A(m, n) = 1/(m + n - 1); end end Cyklus WHILE se provádí dokud je podmínkový výraz roven TRUE. while vyraz prikazy end Př. Následující cyklus hledá nejmenší číslo jehož faktoriál má více než 100 číslic. n = 1; while prod(1:n) < 1e100 n = n + 1; - 3/24 - end Uvnitř cyklu je možné použít speciální příkazy continue a break. Tyto příkazy pokračují v cyklu (continue) nebo ho přeruší (break). Odpovídají příslušným příkazům např. z Pascalu. - 4/24 - 5.4 Funkce – základy Funkce v Matlabu má vstupní argumenty a vrací hodnotu. Proměnné jsou ve vlastním paměťovém prostoru (každá funkce má svůj vlastní workspace). To může být někdy nevýhodné, Matlab ovšem umožňuje pracovat i s globálními proměnnými. Př. function y = prumer(x) % PRUMER(x) prumer z hodnot vektoru x - prvni radek = help y = sum(x)/length(x); % vypocet Definice: klíčové slovo function, výstupní argumenty, = název funkce, vstupní argumenty Funkce je uložena v souboru název funkce.m První řádek s komentářem hned po definici odpovídá nápovědě, můžeme ověřit příkazem help prumer Funkce se volá pomocí svého jména, pozor na záměnu názvu funkce s proměnnou, např. cisla = 1:100; prumer = prumer(cisla) způsobí chybu (proměnná se jmenuje stejně jako funkce), správně by mělo být např. cisla = 1:100; pr = prumer(cisla) pr = 50.5000 Funkci nyní vylepšíme o kontrolu vstupních parametrů function y = prumer(x) % PRUMER(x) prumer z hodnot vektoru x - prvni radek = help % vstupy ktere nejsou vektorem zpusobi chybu [m,n] = size(x); % vrati velikost matice x, m = pocet radku, n=pocet sloupcu if (~((m == 1) | (n == 1)) | (m == 1 & n == 1)) %podminka & je logicky AND, | je logicky OR error('chyba - vstupem funkce prumer neni vektor') end y = sum(x)/length(x); % vypocet Další vylepšení funkce o možnost pracovat s maticí jako argumentem. Pro lehké zesložitění požadujeme aby funkce pracovala po sloupcích, nikoli po řádcích. Jedním z řešení je pouze invertovat vstupní matici (funkce sum a length umí pracovat s maticemi), dalším řešením je použít výpočet v cyklu. Řešení pomocí inverze bude vždy rychlejší, snadno ověříme pomocí funkce sledování délky provádění tic (spouští timer) a toc (zastavuje timer a zobrazí dobu provádění od spuštění). - 5/24 - function y = prumer1(x) % PRUMER(x) prumer z hodnot matice x - prvni radek = help % prumerujeme po sloupcich [m,n] = size(x); % vrati velikost matice x, m = pocet radku, n=pocet sloupcu x = x'; y = sum(x)/length(x); % vypocet function y = prumer2(x) % PRUMER(x) prumer z hodnot matice x - prvni radek = help % prumerujeme po sloupcich [m,n] = size(x); % vrati velikost matice x, m = pocet radku, n=pocet sloupcu for j = 1:m y(j) = 0; for k = 1:n y(j) = y(j) + x(j,k); end; end; for j = 1:m y(j) = y(j) / n; end; % test rychlosti jednotlivych reseni – skript spuštěny primo z workspace a = [1 2 3 4 5; 6 7 8 9 0]; tic; prumer = prumer1(a); toc tic prumer = prumer2(a); toc % vysledek % Elapsed time is 0.000051 seconds. % Elapsed time is 0.000105 seconds. Neřešené úlohy 1. Funkce která transformuje vstupní vektor do mezí určených dalším parametrem. Hlavička funkce: function y = transformace(x,meze) % transformuje vektor (matici) x tak, aby minima a maxima % transformovane funkce byla urcena argumentem meze % priklad volani: % x = sin(1:100); % meze(1) = 2; % meze(2) = 5; % novex = transformace(x,meze) 2. Funkce která najde extrémy vektoru (matice). U matice pozor, výsledky mají různou délku podle toho kolik extrémů má ten který vektor. Možné řešení je buď v prvním prvku daného sloupce uvádět počet extrémů (zbytek budou nuly), dalším řešením je použít cell array (indexace ve složených závorkách – umožňuje ukládat zcela rozdílné typy dat). Hlavička funkce: function vysledky = extremy(x) % funkce vraci extremy funkce x, vektoru ci matice - 6/24 - 5.4.1. Předávání parametrů V Matlabu se předávají parametry pouze hodnotou, nikoliv odkazem. Pokud tedy předám např. parametr a a uvnitř funkce ho změním, jeho hodnota v hlavním workspace se nezmění (předaný parametr funguje jako lokální proměnná dané funkce). Jako argument funkce může být libovolný typ: vektor, matice, pole, cell array, struktura, objekt, atd. Pokud pracujeme s proměnným počtem argumentů, lze využít funkcí pro práci s argumenty: nargin nargout varargin varargout vrací počet vstupních argumentů (integer) dtto pro výstupy vrací cell array s jednotlivými argumenty vstupů (různé typy, počet prvků dle hodnoty nargin) dtto pro výstup Příklad na narargin function c = soucet(a,b) if narargin < 2 error('k souctu potrebuju dva argumenty'); end; Příklad na varargin function argumenttest(varargin) for i=1:length(varargin) x = varargin{i}; disp(class(x)); end; z workspace potom: >> s.name = 'ferda'; >> argumenttest('ahoj',100,1:100,s); char double double struct Je možné předepsat i určitý počet argumentů a k nim potom volitelné argumenty. V tom případě je v hlavičce funkce nejprve n argumentů vyžadovaných a potom varargin, čili: function predepsane2arg(arg1,arg2,varargin) Z pochopitelných důvodů musí být varargin uveden ve výčtu argumentů jako poslední. 5.4.2 Primární funkce, subfunkce, vnořené funkce Funkce která je v m-souboru jako první je takzvaná funkce primární. M-soubor může dále obsahovat další funkce, které slouží funkci primární. Primární funkce je jediná z daného msouboru, kterou je možné volat z příkazové řádky Matlabu nebo z dalších m-funkcí. - 7/24 - Další funkce v m-souboru mohou být buď tzv. subfunkce (subfunctions) nebo vnořené funkce (nested functions). Liší se podle toho, zda jsou za primární funkcí (subfunkce) nebo uvnitř (vnořené funkce). Příklad na subfunkce (následují za primární funkcí) function [prm, med] = statistika(u) % Primarni funkce % STATISTIKA pocita prumer a median pomoci vnitrnich funkci n = length(u); prm = prumer(u, n); med = median(u, n); function a = prumer(v, n) % Pocita prumer a = sum(v)/n; % Subfunkce function m = median(v, n) % Pocita median w = sort(v); if rem(n, 2) == 1 m = w((n+1) / 2); else m = (w(n/2) + w(n/2+1)) / 2; end % Subfunkce Funkce statistika vrací dvě hodnoty, proto při volání je nutné použít a = [1 2 5 4 7 8 4 7 8]; [prumer,median] = statistika(a) Při volání subfunkce se nejprve prohledá daný m-soubor, jestli je v něm subfunkce toho jména, teprve potom se hledá zda se nejedná o standardní funkci Matlabu nebo o funkci která je v cestě. Je tedy možné bez obav přepsat funkci Matlabu, provede se funkce v m-souboru. Subfunkce může obsahovat vlastní help, který je dostupný přes operátor >. help statistika>median Příklad na vnořené funkce (uvnitř primární funkce) function x = A(p1, p2) %primarni funkce ... function y = B(p3) % vnorena funkce ... end % musi byt ukoncena klicovym slovem end function z = C(p4) % vnorena funkce ... end % musi byt ukoncena klicovym slovem end ... end % ukonceni primarni funkce Příklad na násobné vnořené funkce (uvnitř primární funkce) function x = A(p1, p2) % primarni funkce ... function y = B(p3) % vnorena funkce (v primarni funkci) ... - 8/24 - function z = C(p4) % vnorena funkce ve funkci B ... end ... end ... end Při volání vnořených funkcí je možné volat funkce stejné úrovně a funkce o úroveň nižší (ve výše uvedeném příkladu nemůže primární funkce volat funkci C). Každá vnořená funkce má svůj vlastní workspace, ale může navíc vidí (a může modifikovat) všechny proměnné z funkcí ve kterých je vnořena. Je-li např ve funkci A v příkladu proměnná x, může s ní vnořená funkce C pracovat. 5.4.3 Privátní funkce Privátní funkce jsou funkce které jsou umístěny v adresáři s názvem private a které je možné spouštět pouze z funkce která je v nadřazeném adresáři. Privátní funkce nejsou viditelné pro ostatní funkce Matlabu. Toho se využívá v případě že potřebuji funkci přiřadit stejné jméno jako už má nějaká funkce která v Matlabu je, neboť Matlab nejprve prohledává adresář private a teprve potom hledá další funkce na cestě. Je tak možné vytvořit celou řadu funkcí se stejným názvem které ale dělají vždy něco jiného, podle toho které nadřazené funkci slouží. 5.4.4 Přetěžované funkce Jsou funkce které mají různý počet a typ argumentů. V Matlabu jsou podporovány. Příkladem je např. funkce plot která se chová různě podle toho kolik a jakých argumentů do ní vstupuje. Pokud bychom chtěli vytvořit „verzi“ funkce plot, která korektně vykreslí např. datový typ (nebo třídu) ferda, vytvoříme adresář @ferda, ve kterém bude funkce plot pro daný datový typ implementována. Při volání funkce plot se projedou všechny příslušné adresáře a vybere se ta funkce plot, která „se hodí“ pro daný datový typ. Bližší informace o třídách v kapitole o OOP. Jednotlivé implementace funkce zjistíme příkazem which -all plot 5.4.5 Kdo jak na koho volá Při volání funkce je možné že tato volá další funkce. Abychom zjistili které funkce jsou volány, můžeme použít příkaz inmem. Použití je následující: 1. vyčistíme paměť příkazem clear. 2. spustíte funkci o níž chcete zjistit dané informace 3. spustíte funkci inmem. Je možné zjistit i detailnější výpis použitých funkcí pomocí příkazu depfun. - 9/24 - 5.5 Lokální / globální proměnné Každá funkce v Matlabu má svůj vlastní workspace a proměnné v ní definované tudíž „nejsou vidět“ v ostatních funkcích. Jedná se o lokální proměnné. Pokud potřebujeme proměnnou kterou vidí více funkcí, použijeme proměnnou globální. Globální proměnná se deklaruje klíčovým slovem global. Př. function vysledek = testik(vstup) % testik - testovaci funkce global ALFA; vysledek = ALFA * vstup; v hlavním workspace vytvoříme proměnnou ALFA = 10; Při spuštění funkce testik bude tato proměnná použita ALFA = 10; testik(10) ans = 100 Pozn. Při použití globálních proměnných pozor na jejich přepsání uvnitř funkce. Takto přepsaná proměnná má již novou hodnotu i v hlavním workspace a při použití v dalších funkcích. 5.6 Chráněné bloky Matlab má obdobu chráněných bloků. try prikaz ... prikaz catch prikaz ... prikaz end Příkazy mezi try a catch jsou prováděny tak dlouho dokud se všechny neprovedou nebo nedojde k chybě. Pokud dojde k chybě, provedou se příkazy mezi catch a end. - 10/24 - 5.7 OOP (objektově orientované programování) 5.7.1 základy Následující text předpokládá alespoň částečnou znalost OOP, neměl by být problém termín třída, instance třídy, metoda třídy, dědičnost. Matlab částečně podporuje OOP, ale některé jeho klasické rysy zde nenajdeme a i konvence volání atd je poněkud jiná. Obdobně jako u klasického OOP je v Matlabu třída entita, která obsahuje data a metody na operaci s nimi. Třída tak zapouzdřuje data a funkce. Matlab podporuje dědičnost, a to z jednoho i více předků. Třída může obsahovat další třídy. Všechny datové typy v Matlabu jsou uvažovány jako základ třídy (viz. obr.). Pro uživatelské třídy se vychází z datového typu structure (bude bráno jako obdoba TObject v C++, Delphi). Datový typ structure funguje jako pole obsahující pojmenované položky různých typů. Př. pacient.jmeno = 'Josef Novak'; pacient.vaha = 105.00; pacient.test = [79 75 73; 180 178 177.5; 220 210 205]; Instance třídy se vytvoří voláním konstruktoru, který má stejné jméno jako vlastní třída. Metody třídy se nevolají klasickou tečkovou či šipkovou konvencí jako něco co patří třídě, ale jako samostatné funkce, které mají instanci třídy v argumentu. Př. Delphi: nechť pacient je instancí třídy TPacient. Volání metody ZvedniDavkuPenicilinu(argument1, argument2) je logicky vázáno na instanci: vysledek := pacient. ZvedniDavkuPenicilinu(argument1, argument2); Matlab: volám metodu jako nezávislou funkci [vysledek] = ZvedniDavkuPenicilinu(pacient,argument1,argument2); - 11/24 - Jednotlivé metody třídy (případně i instance třídy) lze vypsat příkazem m = methods('classname') m = methods('object') To že je nějaká metoda vlastně metodou objektu je zařízeno fyzickým umístěním funkce do adresáře třídy. Adresář třídy se jmenuje stejně jako třída, ale začíná zavináčem: C:\matlab\ruja\@mojetrida\ 5.7.2 Privátní metody Jsou metody které mohou být volány pouze z public metod třídy. Jsou umístěny v podadresáři private adresáře třídy. C:\matlab\ ruja\@mojetrida\private\ Privátní metody a privátní funkce se liší pouze přítomností třídy jako prvního argumentu funkce. 5.7.3 Vytvoření třídy Jelikož hlavní roli hraje umístění adresáře ve kterém je definice třídy uvedena, je nutné přidat do cesty Matlabu příslušný adresář, a to nikoliv přímo adresář s definicí ale adresář nadřízený, podle příkladu výše uvedeného to bude tedy pomocí příkazu addpath: addpath C:\matlab\ ruja v daném adresáři se musí nacházet konstruktor třídy. To je m.file, který se jmenuje stejně jako třída (mojetrida.m). Voláním konstruktoru se vytvoří instance třídy. Konstruktor musí být schopen umět zpracovat tři různé argumenty: - prázdný argument – vytvoří se defaultní objekt - datový argument – vytvoří se objekt s daty dle argumentů - objektový argument – vrátí zpět daný argument (+ kontrola na shodnost typu) Uvnitř konstruktoru je vhodné použít funkci class, která přiřadí třídě jméno. a = class(a,'mojetrida'); 5.7.4 Hlavní změny oproti klasickému OOP • • • • • Metody jsou asociovány s třídou svým fyzickým umístěním na disku a mají jako první argument instanci třídy Neexistuje destruktor (!!!), musí se volat metoda clear Nelze použít předávání parametrů odkazem (pouze hodnotou). Pokud metoda mění vlastnosti instance, musí vracet danou změněnou instanci a při volání takové metody musí být použito přiřazení. mujobjekt = metoda(mujobjekt, arg1,….) Neexistují abstraktní třídy Neexistují virtuální metody - 12/24 - 5.7.5 Příklad Tvorba třídy pacient, která má 4 datové položky: jméno, příjmení, váha, teplota. Vytvoříme si adresář @pacient, do kterého budou ukládány všechny metody třídy. Nadřízený adresář musí být v cestě Matlabu (příkaz addpath). 5.7.5.1. Konstruktor – musí zabezpečit tvorbu s různými vstupními argumenty function a = pacient(varargin) % konstruktor pacienta % vstup jmeno, primeni, vaha, teplota switch nargin case 0 %zadne parametry, vytvori defaultni objekt a.jmeno = 'neznamy'; a.prijmeni = 'neznamy'; a.vaha = 0; a.teplota = 0; a = class(a,'pacient'); case 1 % jeden argument, predpoklada se instance pacienta if (isa(varargin{1},'pacient')) a = varargin{1} else error('Spatny argument') end; case 4 % vsechny argumenty odpovidaji a.jmeno = varargin{1}; a.prijmeni = varargin{2}; a.vaha = varargin{3}; a.teplota = varargin{4}; a = class(a,'pacient'); otherwise error('Spatny pocet argumentu'); end; % switch Vytvoření instance z workspace je možné buď bez nastavení hodnot vlastností nebo s hodnotami: p = pacient p= pacient object: 1-by-1 p = pacient('josef','novak',50,38) p= pacient object: 1-by-1 - 13/24 - 5.7.5.2. Přístupové metody Základní jsou dvě přístupové metody: set a get na nastavení a získání jednotlivých vlastností přímo pomocí jmen těchto vlastností. U metody get je možné nadefinovat uživatelské vlastnosti. function val = get(a, propName); % vraci prislusne datove polozky, mozno i ruzne kombinovat switch propName case 'jmeno' val = a.jmeno; case 'prijmeni' val = a.prijmeni; case 'vaha' val = a.vaha; case 'teplota' val = a.teplota; case 'celejmeno' % nova vlastnost, nedefinovana v datech val = strcat(a.prijmeni,', ',a.jmeno); otherwise error([propName, 'neni polozka pacienta']); end; % case Voláním metody získáme informaci i objektu, např: get(p,'celejmeno') ans = novak,josef Pro nastavení vlastností se použije metoda set: function a = set(a, varargin); % nastavuje pristlusne datove polozky propertyArgIn = varargin; while length(propertyArgIn) >= 2 prop = propertyArgIn{1}; valu = propertyArgIn{2}; % vzdy oznaceni property a hodnota propertyArgIn = propertyArgIn(3:end); % "odmazu" prvni dve switch prop case 'jmeno' a.jmeno = valu; case 'prijmeni' a.prijmeni = valu; case 'vaha' a.vaha = valu; case 'teplota' a.teplota = valu; otherwise error('Chyba, polozky pacienta jsou jmeno, prijmeni, vaha, teplota'); end; % switch end % while - 14/24 - Volání metody může uvádět argumenty v libovolném pořadí a pouze některé, případně všechny najednou (třída ovšem musí již být vytvořena konstruktorem !): p = set(p,'jmeno','karel','prijmeni','havlicek','vaha',500,'teplota',50) p= pacient object: 1-by-1 get(p,'celejmeno') ans = havlicek,karel Další přístupové metody jsou založeny na indexovaném přístupu, s tím že typ indexu může být různý. Indexové přístupové metody pak musí být schopny ošetřit všechny typy indexů. Pokud nejsou metody definovány není možné samozřejmě indexovaný přístup použít. Opět jsou metody dvě, pro čtení a zápis: subsref a subsasgn: function b = subsref(a,index) % SUBSREF pro pacienta - vraci prislusne hodnoty dle indexu switch index.type case {'()','{}'} % stejny pristup pro klasicky index i cell array switch index.subs{:} case 1 b = a.jmeno; case 2 b = a.prijmeni; case 3 b = a.vaha; case 4 b = a.teplota; otherwise error('Index mimo rozsah') end % switch index.subs case '.' switch index.subs case 'jmeno' b = a.jmeno; case 'prijmeni' b = a.prijmeni; case 'vaha' b = a.vaha; case 'teplota' b = a.teplota; case 'celejmeno' % nove vytvorena vlastnost, neni definova v datech b = strcat(a.prijmeni,',',a.jmeno); otherwise error('Neplatne jmeno polozky') end % switch index.subs end % switch index type Použití: >> p.jmeno ans = karel - 15/24 - >> p.celejmeno ans = havlicek,karel >> p(1) ans = karel >> p{1} ans = karel Metoda pro indexovaný zápis: function a = subsasgn(a,index,val) % SUBSASGN pacient - zapis do vlastnosti switch index.type case {'()','{}'} % opet pro oba typy indexu switch index.subs{:} case 1 a.jmeno = val; case 2 a.prijmeni = val; case 3 a.vaha = val; case 4 a.teplota = val; otherwise error('Index mimo rozsah') end case '.' switch index.subs case 'jmeno' a.jmeno = val; case 'prijmeni' a.prijmeni = val; case 'vaha' a.vaha = val; case 'teplota' a.teplota = val; otherwise error('Neplatne jmeno polozky') end end použití: >> p.jmeno = 'Antonin'; >> p.jmeno ans = Antonin Zobrazení objektu metodou Display: function display(a) - 16/24 - % display pro pacienta s = sprintf('Jmeno: %s\nPrijmeni: %s\nVaha: %9.2f\nTeplota: %9.2f',... a.jmeno,a.prijmeni,a.vaha,a.teplota); disp(s); 5.7.6. Příklad – rozšíření o dědění Vytvořme dva dědice třídy pacient – noha a srdce. Obě třídy dědí vlastnosti pacienta a přidávají další specifické vlastnosti: noha bude mít vlastnost ktera (leva, prava, obe), srdce bude mít vlastnost EKG (vektor). Nejprve třída noha: konstruktor, metody display, set, get, subsref a subsasgn. 5.7.6.1. Konstruktor a zobrazovací metoda display: function a = noha(varargin) % konstruktor dedice pacienta - noha % vstup puvodni vlastnosti pacienta (jmeno, primeni, vaha, teplota) % pridany vstup "ktera" typu retezec (leva, prava, obe) switch nargin case 0 %zadne parametry, vytvori defaultni objekt a.ktera = 'neurceno'; s = pacient; a = class(a,'noha',s); case 1 % jeden argument, predpoklada se instance pacienta if (isa(varargin{1},'noha')) a = varargin{1} else error('Spatny argument') end; case 5 % vsechny argumenty odpovidaji a.ktera = varargin{5}; s = pacient(varargin{1},varargin{2},varargin{3},varargin{4}); a = class(a,'noha',s); otherwise error('Spatny pocet argumentu'); end; % switch Volání konstruktoru je obdobné jako u předka, buď bez parametrů, nebo již se všemi parametry: n = noha('josef','novak',100,38,'leva'); n = noha; Metoda display využívá tutéž metodu předka: function display(a) % display pro noha pacienta display(a.pacient); s = sprintf('Ktera: %s',a.ktera); disp(s); - 17/24 - 5.7.6.2. Přístupové metody Obdobě jako u předka definujeme přístupové metody pro čtení a zápis a to jak přímé (get a set), tak indexované (subsref a subsasgn). Zděděné vlastnosti musí být bohužel v přístupových metodách explicitně znovu uvedeny, i když pouze volají příslušné metody předka. Je nicméně v principu možné tak přístupové metody ke zděděným vlastnostem zcela změnit. function val = get(a, propName); % vraci prislusne datove polozky pro pacienta-noha, mozno i ruzne kombinovat switch propName % puvodni zdedene vlastnosti case 'jmeno' val = get(a.pacient,'jmeno'); case 'prijmeni' val = get(a.pacient,'prijmeni'); case 'vaha' val = get(a.pacient,'vaha'); case 'teplota' val = get(a.pacient,'teplota'); case 'celejmeno' val = get(a.pacient,'celejmeno'); % nova vlastnost case 'ktera' val = a.ktera; otherwise error([propName, 'neni polozka pacienta']); end; % case Volání je stejné jako u předka: >> get(n,'ktera') ans = prava Obdobně metoda set: function a = set(a, varargin); % nastavuje pristlusne datove polozky pro noha pacienta propertyArgIn = varargin; while length(propertyArgIn) >= 2 prop = propertyArgIn{1}; valu = propertyArgIn{2}; % vzdy oznaceni property a hodnota propertyArgIn = propertyArgIn(3:end); % "odmazu" prvni dve switch prop % zdedene vlastnosti se nastavuji pomoci zdedene metody set - je nutno % to cele znovu natukat, v tomto je OOP v matlabu :-((( case 'jmeno' a.pacient = set(a.pacient,'jmeno',valu); case 'prijmeni' a.pacient = set(a.pacient,'prijmeni',valu); case 'vaha' a.pacient = set(a.pacient,'vaha',valu); case 'teplota' - 18/24 - a.pacient = set(a.pacient,'teplota',valu); % nova vlastnost obdobne jako u predka case 'ktera' a.ktera = valu; otherwise error('Chyba, polozky pacienta noha jsou jmeno, prijmeni, vaha, teplota, ktera'); end; % switch end % while Přístupové metody indexované mohou využívat interní metodu fieldcount, pokud není naprogramována je nutné znát počet položek předka a nastavit jej natvrdo: function b = subsref(a,index) % SUBSREF pro pacienta/noha - vraci prislusne hodnoty dle indexu fc = 4; % nastavim hodnotu poctu vlastnosti predka natvrdo. Je mozne take pouzit % metodu fieldcount u predka (ale to bychom ji museli naprogramovat...) switch index.type case {'()','{}'} % stejny pristup pro klasicky index i cell array if (index.subs{:} <= fc) % predek b = subsref(a.pacient,index); else switch index.subs{:} - fc case 1 b = a.ktera; otherwise error('Index mimo rozsah') end % switch index.subs end % else case '.' switch index.subs case 'ktera' b = a.ktera; otherwise b = subsref(a.pacient,index); end % switch index.subs end % switch index type Obdobně i metoda pro zápis: function a = subsasgn(a,index,val) % SUBSASGN pacient/noha - zapis do vlastnosti fc = 4; % obdobne jako u subsref switch index.type case {'()','{}'} % opet pro oba typy indexu if (index.subs{:} <= fc) % predek a.pacient = subsasgn(a.pacient,index,val); else switch index.subs{:}-fc case 1 a.ktera = val; otherwise error('Index mimo rozsah') - 19/24 - end % switch end % if case '.' switch index.subs case 'ktera' a.ktera = val; otherwise a.pacient = subsasgn(a.pacient,index,val); end end Volání je stejné jako u předka: >> n(5) = 'obe'; >> n Jmeno: josef Prijmeni: novak Vaha: 100.00 Teplota: 38.00 Ktera: obe 5.7.7. Příklad – neřešená úloha U výše uvedeného příkladu vytvořte metody pro třídu srdce. 5.7.8. Další specialitky OOP 5.7.8.1. Dědění z více předků V matlabu je možné dědit ze dvou i více předků. V konstruktoru jednoduše použijete v metodě class více argumentů. Například když bychom chtěli (i když by to byl důkaz špatného objektového návrhu) vytvořit novou třídu z noha a srdce a přidat mu navíc vlastnost rc (rodné číslo), (to že mají společného předka není nutné, je to jen náhoda v daném příkladu), bude konstruktor obsahovat: …. s1 = noha; s2 = srdce; a.rc = '710812/5847'; a = class(a,'superpacient',s1,s2); …. Pokud mají předci metody stejného jména, použije se při volání této metody ta, jejíž „majitel“ je uveden ve volání class jako první. Na druhou (další) se už nikdy nikdo nedostane…. 5.7.8.2. Přetěžování operátorů a funkcí V matlabu je možné předefinovat operátory tak, aby byly schopny pracovat s objekty. Například můžeme předefinovat význam + aby bylo možné sečíst dvě instance stejné třídy. Pro definici je třeba napsat funkci třídy s příslušným názvem, například + plus, - minus, * mtimes, atd. Kompletní výpis názvů operátorů je v helpu. Hlavička takové funkce přetěžovaného operátoru pak bude vypadat: function r = plus(p,q) - 20/24 - kde p a q jsou instance příslušné třídy a r je instance obsahující výsledek operace. Obdobně je možné přetěžovat i běžné funkce Matlabu tak, aby byly schopné pracovat s daným objektem. Příkladem může být funkce plot, pro kterou existuje mnoho variant takže je schopna zpracovat celou řadu objektů. - 21/24 - 5.8 Profiler 5.8.1 Profilování Při práci s většinou Matlabem nejprve programujeme funkcionalitu a po odladění funkce se začneme zabývat rychlostí. K tomu je v Matlabu dostupný nástroj - profiler - který během činnosti programu vyhodnocuje počty volání jednotlivých funkcí, dobu trvání těchto funkcí až na úroveň jednotlivých řádků, a podobně. 5.8.2 Spuštění profileru Z příkazové řádky příkazem profile on Spuštěním profileru od této chvíle jsou zaznamenávány časy a počty volání všech M-souborů, respektive jednotlivých řádků a funkcí, včetně vnořených. 5.8.3 Jednoduchý příklad Vytvoříme jednoduchý M-soubor, viz. obrázek. Uložíme např. pod názvem profiler_test.m. Se spuštěným profilerem spustíme M-soubor, z příkazové řádky napsáním jeho názvu. Po doběhnutí souboru spustíme analýzu profileru, z příkazové řádky příkazem profile report Otevře se nové okno, ve kterém jsou zobrazeny počty volání a časy funkcí: - 22/24 - Výběrem konkrétní funkce (v našem případě M-souboru profiler_test) získáme podrobný výpis profileru pro tuto funkci. - 23/24 - - 24/24 -
Podobné dokumenty
MATLAB ver. 5
Adresace podpole pole A definovaná vektorem řádkových indexů
r a vektorem sloupcových indexů c.
Adresace podpole pole A definovaná vektorem řádkových indexů
r a všemi sloupci.
Adresace podpole pole...
Shoptronic-novinky
tato možnost doplňuje ruční vstup úhrad
- možnost definovat na kartě zboží (ALT/F9) položku MINIMÁLNÍ MNOŽSTVÍ PRO PŘIJATOU
OBJEDNÁVKU – vazba na přijaté objednávky, vydané objednávky, příjem, přev...
Hlavní dokument - Technologie společnosti Microsoft pro vývoj
pro použití v tomto dokumentu a otestovány jako funkční. Nicméně na různých konfiguracích může
dojít k různým chybám, proto je třeba je brát hlavně jako ilustrační příklady.
Některé kódy mají souvi...
Implementace hry „Had“ (angl. Snake) pomocí GUI
Ze dvou nabízených témat k naprogramování v Matlabu na poslední úkol jsem si zvolil
vytvoření aplikace pomocí GUI. Jelikož jsem chtěl vytvořit nějaký program, který by
obsahoval jak formulář s menu...
Návod - žaluzie ENERGIE s komfrotním ovladačem
12.1. Základní funkce tlacítek nahoru/dolu .............................................................................................................................. 38
12.2. Nastavení žaluzie ...
Reprezentace Booleovských funkcí
Z věty plyne také vyjádření funkce obvodem velikosti O(2n ). Později, konkrétně pomocí Vět 4.1 a 3.1 ukážeme, že každou funkci n proměnných lze reprezentovat obvodem velikosti O(2n /n).
Pro konstru...
Metoda Rayleighova podílu
• Vytvořené funkce budou obsahovat nápovědu
• Funkce budou realizovány s proměnným počtem parametrů
• Bude ošetřeno zadání chybného počtu parametrů a chybné zadání jejich hodnot
• Vstupní data bude...
Měnič frekvence Rexroth
2 Bezpečnostní pokyny pro elektrické pohony a řízení
2.1 Všeobecné informace
Než začnete pracovat se zařízením, přečtěte si a pochopte tyto bezpečnostní pokyny a celou uživatelskou dokumentaci. Nem...
Standardizace v ITS
do provozu. Pro fyzický systém to bude proces, který umožní
jeho používání v konkrétní lokalitě. V případě architektury to
znamená její přípravu tak, aby byla k dispozici při vývoji
vlastního fyzic...