Rösta på artikeln
Procedurer och funktioner
De procedurer som vi hanterat i tidigare avsnitt har alla varit
händelseprocedurer som Delphi ställt i ordning en stomme till. Vi skall nu ge oss
på att skapa några egna procedurer som inte nödvändigtvis behöver vara kopplade till
någon komponent.
Ett exempel på en procedur
Anta att vi har tillverkat ett program som innehåller tre editeringsrutor,
som vi vill tömma vid olika tillfällen. Vi skulle kunna lösa det genom att lägga till
en knapp på formuläret och sedan skriva kod för detta. Men denna metod förefaller
lite överarbetad. Istället löser vi detta genom att skriva en fristående procedur.
Vi börjar med att skriva in proceduren namn i formulärets Private-del.
private
{ private declarations }
procedure RensaTextrutor; //Detta lägger du till
public
{ public declarations }
end; |
Vi lägger deklarationen i private-delen, därför att inga andra
enheter som vi eventuellt använder oss av, skall kunna använda denna procedur. Detta
är en allmän princip. Det som inte andra delar behöver känna till, skall de fortfarande
vara ovetande om.
Detta räcker emellertid inte utan vi måste också tala om för
kompilatorn vad proceduren skall utföra. Vi måste implementera proceduren. I enhetens
implementationsdel, förslagsvis efter kompileringsdirektivet.
implementation
{$R *.DFM}
procedure TForm1.RensaTextrutor;
begin
Edit1.Text := '';
Edit2.Text := '';
Edit3.Text := '';
end; |
Lägg märke till att vi måste tala om för kompilatorn att detta
är en procedur som är knuten till formulärtypen TForm1. Det räcker alltså inte med
att bara skriva
procedure RensaTextrutor;
Varje gång som vi nu behöver rensa de tre textrutorna räcker
det med att skriva
RensaTextrutor;
Ett exempel på en funktion
Underprogram kan också utgöras av funktioner. En
funktion fungerar precis som en procedur med enda undantaget att den returnerar ett
värde. Detta värde kan man lagra i en variabel, använda den i ett beräkningsuttryck,
skriva ut på skärmen etc.
Observera att man i princip kan använda en funktion överallt
där man annars använder en konstant. Till skillnad från en konstant, som har ett konstant
värde, beräknar en funktion alltid det värde den returnerar.
Värdet som en funktion returnerar kan vara av olika datatyp.
Funktionens värde måste därför deklareras vad beträffar datatypen, precis på samma
sätt som man anger datatypen för en variabel.
Vi skall visa hur en funktion ser ut genom att skriva ett enkelt
program där vi anger sidorna i en triangel.
Placera ut komponenter på ett formulär enligt bilden nedan.
Dubbelklicka på knappen och skriv in följande händelseprocedur.
procedure TForm1.BitBtn1Click(Sender: TObject);
var
a,b,c : double;
ok : boolean;
begin
a := StrToFloat(Edit1.Text);
b := StrToFloat(Edit2.Text);
c := StrToFloat(Edit3.Text);
ok := (a+b>c) and (a+c>b) and (b+c>a);
if ok then
Label4.caption := 'Detta kan vara sidor i en triangel'
else
Label4.caption := 'Detta är inga triangelsidor';
end;
|
Kör programmet och testa olika sidor. I händelseproceduren används
en logisk variabel ok. Den skall innehålla värdet av testen att sidorna utgör triangelsidor,
vilket den får i satsen
ok := (a+b>c) and (a+c>b) and (b+c>a);
Anta nu att vi utvidgar vårt program till en jätteprogram.
På flera ställen i programmet får vi anledning till att testa om sidorna kan vara
triangelsidor. I annat fall skrivs motsatsen ut. Vi lägger då nyss skrivna procedur
i en funktion istället. Så här kan en sådan funktion se ut.
private
{ private declarations }
procedure RensaTextrutor; //Detta lägger du till
public
{ public declarations }
end;
implementation
{$R *.DFM}
function TForm1.SidorOK : boolean;
var a,b,c : double;
begin
a := StrToFloat(Edit1.Text);
b := StrToFloat(Edit2.Text);
c := StrToFloat(Edit3.Text);
SidorOK := (a+b>c) and (a+c>b) and (b+c>a);
end;
|
Sedan ändrar vi proceduren för knappen på följande sätt.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
//SidorOK ger samma värde som ok tidigare.
if SidorOK then
Label4.caption := 'Detta kan vara sidor i en triangel'
else
Label4.caption := 'Detta är inga triangelsidor';
end;
|
När vi nu behöver testa våra triangelsidor räcker det med att
anropa funktionen med att skriva SidorOK så får vi reda på det.
I deklarationen av funktionen kallas den första satsen
function TForm1.SidorOK : boolean;
för funktionshuvudet. Det börjar med det reserverade ordet function och
följs av namnet på funktionen. Därefter anges datatypen på det värde som funktionen
skall returnera. Eftersom vi knutit funktionen till formulärtypen måste vi kvalificera
namnet på funktionen SidorOK med TForm1.
Det vanligaste felet vid funktioner är att man glömmer att returnera
ett värde, dvs. man glömmer att sätta funktionsnamnet lika med det värde som skall
returneras. Kompilatorn protesterar inte mot detta!
Beträffande händelseproceduren för OK-knappen behöver vi inga
lokala variabler för att uföra några tester. Här överlåts alla tester till funktionen SidorOK.
Värdeparametrar till underprogram
Vi har tidigare tagit upp underprogram som använder sig av parametrar,
t ex standardfunktionen Succ.
Succ returnerar efterföljaren till det den anropas med.
Label1.Caption := Succ('A'); { Ett B skrivs ut på
etiketten }
Efter Succ anger vi det vi vill att Succ skall arbeta
med. Till funktionen överlämnas data, ett argument, via en inkanal som här utgörs
av en värdeparameter. Hur kan deklarationen tänkas se ut? Låt oss se på ett exempel,
där vi begränsar Succ till att arbeta enbart med bokstäver.
function Succ(x:char):char;
{Succ är deklarerat i och med att det står i funktionshuvudet.}
begin
Inc(x);
Succ := x;
end;
|
I funktionshuvudet deklareras i parentesen efter namnet på funktionen
en värdeparameter x av datatypen char. Efter parentesen skriver vi ett kolon och datatypen
på det värde som funktionen skall returnera.
Den datatyp som anges för parametrar måste vara deklarerad tidigare,
dvs. vara en datatyp som är standard eller tidigare deklarerad i en type-deklaration.
I parameterlistan får alltså inte ingå någon form av typbeskrivning.
Vid ett anrop av Succ kommer x att fungera som en inkanal, dvs
ha ett värde som funktionen kan utnyttja. Alla värdeparametrar fungerar som lokala
variabler som får sina värden vid anrop av underprogrammet. Man får funktionen att
returnera ett värde genom att tilldela funktionsnamnet själva returvärdet, Succ :=
x.
|