17 Mart 2018 Cumartesi

Generic (soysal) listeler ve kullanımı - 1

Delphi de diğer dillerdeki gibi Generic listeleri object pascal içine alarak dildeki önemli geliştirmelerden birini gerçekleştirmiş oldu.

Generic nedir: Bir listeye, liste elemanı olacak şeyin (değişken, nesne ve her neyse) tipini vererek, liste içinde yapılan tüm işlemlerin bu tipe göre yapılmasını sağlayabilen listelerdir.

Örnek verirsek, önce bir Console projesi yaratalım. Sonra aşağıdaki kodları yazalım

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  tamsayiliste : TList<Integer>;
  i : integer;
begin
  tamsayiliste := TList<Integer>.Create;
  tamsayiliste.Add(181);
  tamsayiliste.Add(22);
  tamsayiliste.Add(11); 
  tamsayiliste.Add(17);
  for i in tamsayiliste do
    WriteLn(i);
  ReadLn;
end.

Bunu çalıştırdığımızda sırayla eklediğimiz rakamları yazacaktır. Bu listeye farklı tipte bir eleman eklemeye çalıştığımızda derleme esnasında hata verecektir. Bu da bize büyük esneklik sağlayan bir gereç veriyor. 
Bize ne sağlar: Her ayrı tip için ayrı bir liste sınıfı yazmamız gerekiyordu.
Önceden TList kullandığımızda elemenın tipi Pointer idi. Haliyle bunu şu şekilde yapıyorduk;

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  lst : TList;
  i : integer;
begin
  lst := TList.Create;
  lst.Add(Pointer(181));
  lst.Add(Pointer(22));
  lst.Add(Pointer(11));
  lst.Add(Pointer(17));
  for i:=0 to lst.Count-1 do
    WriteLn(IntToStr(Integer(lst[i])));
  ReadLn;
end.
Eğer string'lerden oluşan bir liste istiyorsak TStringList'i kullanmak ya da TList'i değiştirmek gerekiyordu. Şimdi ise bunlara hiç gerek kalmadı. Yapmamız gereken sadece;

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  lstr : TList<string>;
  s : string;
begin
  lstr := TList<string>.Create;
  lstr.Add('Ahmet');
  lstr.Add('okula');
  lstr.Add('gelecek,');
  lstr.Add('ama yarın...');
  for s in lstr do
    Write(s+' ');
  ReadLn;
end.

Bu listeye string'den başka bir tip eklemeye kalksak bize hata verecektir. Bu da bize, üst düzey dillerin çok önem verdiği ve önemli hata kaynaklarından biri olan, Type Safe (Tip Güvenliği)'ni sağlayacaktır. Yani bir tamsayı listesine başka bir tipte değişkeni eklememizi engelleyecektir.

Generic listeleri her tür class'lar için de kullanabiliriz.

program Project1;
{$APPTYPE CONSOLE}

{$R *.res}
uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections;

type
  TContact = class
    ContactId : Integer;
    ContactName : string;
    BirthPlace : string;
    BirthDay : TDate;
    Gender : string;
    function ToString : string; override;
    constructor Create(aContactId : Integer; aContactName : String; aBirthPlace : String; aBirthDay : TDate; aGender : String);
  end;

{ TContact }

constructor TContact.Create(aContactId: Integer; aContactName, aBirthPlace: String;
  aBirthDay: TDate; aGender: String);
begin
  ContactId := aContactId;
  ContactName := aContactName;
  BirthPlace := aBirthPlace;
  BirthDay := aBirthDay;
  Gender := aGender;
end;

function TContact.ToString: string;
begin
  result := IntToStr(ContactId)+'/'+ContactName+'/'+BirthPlace+'/'+DateToStr(BirthDay)+'/'+Gender;
end;

var
  MyContacts : TList<TContact>;
  fcon : TContact;
begin
  MyContacts := TList<TContact>.Create;
  MyContacts.Add(TContact.Create(1, 'Ahmet Acar', 'Rize', EncodeDate(1977, 1, 10), 'Erkek'));
  MyContacts.Add(TContact.Create(2, 'Çoşkun Pireli', 'Artvin', EncodeDate(1992, 5, 3), 'Erkek'));
  MyContacts.Add(TContact.Create(3, 'Mehmet Kesmez', 'Bolu', EncodeDate(1983, 11, 27), 'Erkek'));
  MyContacts.Add(TContact.Create(4, 'Cahide Küskün', 'Eskişehir', EncodeDate(1996, 6, 12), 'Kadın'));

  for fcon in MyContacts do
    WriteLn(fcon.ToString);
  ReadLn;
end.


Peki bu listeye farklı bir class eklemeye kalkarsak ne olur. Önce yukarıya şöyle bir sınıf tanımlayalım;
type
  TInvalidContact = class
    Id : Integer;
    Name : string;
  end;

daha sonra ise bunu listeye eklemeye çalışalım;
...
...
  MyContacts.Add(TInvalidContact.Create);
...
...
...


İşte Generic listin özelliği burada belli olacak. Bu satıra derleme hatası verecek ([dcc32 Error] Project1.dpr(nn): E2010 Incompatible types: 'TContact' and 'TInvalidContact'). Ve bu tür hatalar da bizi büyük hatalardan koruyacak!...
















1 yorum:

  1. Blogunuzda Delphi ile ilgili çok güzel makaleler var. Bunların tümünü DelphiCan'da da yayınlayın bence. Böylece daha fazla kişi faydalanmış olur.

    YanıtlaSil