Delphi’de Prosedür ve Fonksiyon Parametreleri

Bu yazının bir kısmı pointer ve referansın devamı niteliğinde. “Pointer ve Referans” yazımı okumayanlar önce oraya bi göz atabilirler.
Pointer ve Referans: http://akcakir.net/delphide-pointer-ve-referans/

Delphi’de 4 farklı parametre tanımımız var, bunlar: Var, Out, Const, Value(varsayılan). Bunlarla beraber tipsiz tanımlar da yapabiliyoruz yazımda ona da değindim. Yazının en sonunda ise dizi ve stringlerin parametrede kullanımından bahsettim. Ama yazıma parametreler hakkında temel bilgilerle başlamak istiyorum.

Arka arkaya gelen parametreler aynı tanım ve tipteyse isimler arasına virgül koyabiliriz.

Function Topla(x:Integer; y:Integer):Integer;
Function Topla(x, y:Integer):Integer;

Bir parametreye varsayılan değer vermek için = operatörü kullanabiliriz

Function Topla(x:Integer; y:Integer=10):Integer;

bu fonsiyonu çağırırken;

Topla(1,10);
Topla(1);

İkisi de aynıdır çünkü 2. parametre varsayılan değeri 10 olduğu için yazmadan çağırınca 10 olacaktır.

Bir de karışıklık olmaması koyulmuş bir kural: Bir parametreye varsayılan değer vermek için kendinden sonrakilere de vermiş olmalısınız. Yani, yukarıdaki örnekten konuşursak 1. parametreye varsayılan değer vermek için önce 2. parametreye varsayılan değer vermek zorundasınız.

Overload özelliği aynı fonksiyonu farklı parametre ve dönüş tipleri ile yazmak mümkündür. Overload ile parametre sayıları da değişebilir.

Function Topla(x, y:Integer):Integer; overload;
Function Topla(x, y:real):real; overload;

Function Carp(x, y:Integer):Integer; overload;
Function Carp(x, y:real;z: Integer):real; overload;

Overload edilen fonksiyon çağırılırken yazılan parametrelere uyan versiyonu çalışır.

İkisini bir arada kullanırken çakılmayalım, örneğin;

procedure Topla(x: Integer); overload;
procedure Topla(x: Integer; y: Integer = 10); overload;
Topla(1);

Hangi prosedür çalıştı?, Hiç biri. Derleme hatası! Bu örnekleri başka bir yazıda detaylandırmak isterim. (Böyle diyip muhtemelen unutacağım) konuya başlıklarla devam edelim;

Value:

Aslında böyle bir şey yok. Yani varsayılan tanımımız bu.

Function Topla(x:Integer;y:Integer):Integer;
begin
  x:=x+y;
  Result:=x;
end;

Fonksiyonumuzun sonuç olarak x ve y toplamını döndürecektir. x değişkeninde yaptığımız değişiklik ise fonksiyonun içinde kalacaktır.
Value tanımlanan parametre yerel değişken gibi işleyip değerinin değişmesine izin verir ancak bu değişiklik fonksiyon dışına çıkmaz, yani:

var
  sonuc,x,y:Integer;
begin
  x:=10;
  y:=15;
  sonuc:=Topla(x,y);

  //x değişkeninin değeri hala 10. Parametre value olduğu için fonksiyon içinde yapılan değişiklik buraya yansımayacaktır.
  ShowMessage(IntToStr(x));
end;

Const:

Bu tanım adından da anlaşılabilir, parametreyi sabit yapacaktır. Yani fonksiyon içerisinde atama yapılamaz.

Function Topla(const x:Integer; const y:Integer):Integer;
begin
  x:=x+y;//Bu satır hata verecektir.
  Result:=x+y;
end;

x değişkeninde yaptığımız değişiklik hata verecektir. Çünkü const sabittir.

Var:

Fonksiyon ve prosedür parametresinde de pointer konusunda kolaylığımız “var”! Bu parametre tanımında fonksiyon çağırılırken yazılan değişken referans alınır.
Yani parametre değişken gibi kullanılırken yapılan değişiklikler de fonksiyon dışına çıkacaktır.

Procedure Topla(var sonuc: Integer; //var tanımlama => atama yapılır, yeni değer dışarı çıkar (Pointer)
                x:Integer; //atama yapılır, yeni değer içeride kalır
                const y:Integer); //const tanımlama => atama yapılamaz
begin
  x:=x+10;//value(default) tanımlandığı için atama yapılır ancak yerel değişken gibi içeride kalır.
  y:=y+5;//const tanımlandığı için atama yapılamaz, bu satır hata verir.
  sonuc:=x+y;//var tanımlandığı için atama yapılır ve global değişken gibi dışarı çıkar, yani pointer olur.
end;

Bir de bu prosedürü çağırıp görelim.

var
  sonuc,x,y:Integer;
begin
  x:=10;
  y:=15;
  Topla(sonuc,x,y);

  //sonuc değişkeninin değeri 35, var olarak tanımlandığı için yapılan atama dışarı çıkmıştır.
  ShowMessage(IntToStr(sonuc));

  //x değişkeninin değeri 10, var olarak tanımlanmadığı için yapılan atama dışarı çıkmaz.
  ShowMessage(IntToStr(x));
end;

Nesne değişkenler için pointer benzetmesini önceki yazımda yapmıştım. var parametreler için de yukarıda pointer benzetmesi yaptım. İkisini bir araya getirip bir bakalım;

Procedure ToplaRef(var sonuc: TLabel;x: TLabel;const y:TLabel);
begin
  y:=x;//Bu satır hata verir. çünkü y, const olarak tanımlandı.
  y.Caption:=y.Caption+sonuc.Caption;//Ancak nesneler de birer pointer gibi olduğu için bu atamayı ekranda görebilirsiniz.
  sonuc.Caption:=x.Caption+y.Caption;//Bu satırın çalışmasıyla bir üstteki satırın çalışma mantığı aynıdır.
  //aynı işlemi x ile yapsak o da aynı şekilde çalışırdı.
  x:=sonuc;//artık x ve sonuc aynı nesnenin referansları, yani artık;
  sonuc.Caption:=x.Caption;    //Bu satır ile,
  sonuc.Caption:=sonuc.Caption;//Bu satır aynıdır.
  //fakat bu referans değişimi; x, "var" olarak tanımlanmadığı için metod dışına çıkmaz.
  sonuc:=y;//ancak bu referans değişimi fonksiyon dışına çıkar.
end;

Bir de bu prosedürü çağırıp görelim.

var
  Label1Ref,Label2Ref,Label3Ref:TLabel;
begin
  //Formdaki nesnelere referanslar oluşturalım (Orjinal referansları kullanmıyorum, kaybetmemek için)
  Label1Ref:=Label1;
  Label2Ref:=Label2;
  Label3Ref:=Label3;
  ToplaRef(Label3Ref,Label1Ref,Label2Ref);
  ShowMessage('Label1Ref:'+Label1Ref.Name+#13#10+
              'Label2Ref:'+Label2Ref.Name+#13#10+
              'Label3Ref:'+Label3Ref.Name);
end;

Mesaj kutusundan gördüğümüz üzere, x’in yani Label1Ref’in referans değişimi fonksiyon dışına çıkmazken Label3Ref’in referans değişimi fonksiyon dışına çıkmış.

Out:

Bu parametre tanımı için de var ile aynıdır diyebilirim. Kullanım amacı olarak farklılık gösterir, bunun amacı fonksiyonu çağırırken bir değer almak değil sadece değer çıkışı sağlamaktır.

Procedure Topla(out sonuc: Integer; x:Integer; const y:Integer); 
begin
  x:=x+10;
  y:=y+5;
  sonuc:=x+y;
end;

Tipsiz tanım:

Var, out, const tanımlarda değişken tipi belirtmeden tanım yapabiliriz(value tanımda bu mümkün değildir.)

Procedure Prosedur(const sonuc);
Procedure Prosedur(var sonuc);
Procedure Prosedur(out sonuc);

Tabi bu kullanımda tipi olmamasına rağmen, istediğimizi atayalım gibi bir şey yok. Bu tanım için şöyle bir örnek ekleyim;

function EsitMi(var Deg1, Deg2; Boyut: Integer): Boolean;
type
  TBytes = array[0..MaxInt - 1] of Byte;
var
  N : Integer;
begin
  N := 0;
  while (N < Boyut) and (TBytes(Deg2)[N] = TBytes(Deg1)[N]) do
    Inc(N);
  EsitMi := N = Boyut;
end;

Bu örnekte tip farketmeksizin 2 değişken birbirine eşit mi diye baktık.

Dizi ve string parametre:

Bu bölümü oluşturma sebebim dizi ve short-string parametre alan fonksiyon ve prosedürler farklı olduğundan değil. Sadece bunu type olarak tanımlamadan direk yazarsak sözdizimi hatası alıyor olmamız. Yani;

Short-string parametre oluştururken

function Topla(S1,S2: string[20]):string[20];//Sözdizimi hatası! bu satır hata verir.
type TString20=string[20];//önce tip olarak tanımlıyoruz
function Topla(S1,S2: TString20):TString20;//sonra da o tiple tanımlıyoruz, işte bu doğru tanım

Dizi parametre oluştururken

function Topla(A: array[1..10] of Integer):Integer;//Yine, Sözdizimi hatası!
type TIntDizi10=array[1..10] of Integer;//Aynı şekilde, önce tip olarak tanımlıyoruz
function Topla(S1,S2: TIntDizi10):Integer;//sonra yine o tiple tanımlıyoruz, işte bu doğru tanım

Aslında girmek isteyip de giremediğim detaylar var, ancak yazı çok uzadığı için giremedim. Bu yüzden bu konu üzerine daha sonra bir yazı daha yazabilirim.

Bir dahaki yazılarımda görüşmek üzere hoşçakalın..

Tags: , , , , , , , , , , , , , , , , , ,

No comments yet.

Leave a Reply

*