Matlab05 (431kB

Transkript

Matlab05 (431kB
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

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

Více

Shoptronic-novinky

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

Více

Hlavní dokument - Technologie společnosti Microsoft pro vývoj

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

Více

Implementace hry „Had“ (angl. Snake) pomocí GUI

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

Více

Návod - žaluzie ENERGIE s komfrotním ovladačem

Návod - žaluzie ENERGIE s komfrotním ovladačem 12.1. Základní funkce tlacítek nahoru/dolu .............................................................................................................................. 38 12.2. Nastavení žaluzie ...

Více

Reprezentace Booleovských funkcí

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

Více

Metoda Rayleighova podílu

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

Více

Měnič frekvence Rexroth

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

Více

Standardizace v ITS

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

Více