Statik ve dinamik metodlarin garip dunyasi
// 26 Nisan 2011 // Delphi
Uzun zamandir Delphi ile ilgili bir makale , yazi vs. yazmadim. Birkac kere elim gider gibi oldu ama nedense sonunu getiremedim. Delphi ile ilgili yazilar yazdigim blogu kapattim , kisisel blogumda oylesine duruyor cok ellemiyorum. Biryerlerde insanin login olabilecegi baska wordpressler olmasi guzel sey
Evet yine belki bir makale yazmadim ama guldururken dusunduren 10 tane soru hazirladim. Sorular statik ve dinamik metodlarin calisma mantiklarini birebir gormenizi saglayan cinsten sorular. Gercekten sorulari teker teker programa koyup calistirip ciktilarina baktiginizda insana cok seyler ogretebiliyor. Hatta sorulardan bir tanesini Access Violatin verecegini dusunurek hazirlamistim , calisitirinca Access violation hatasi vermeyince bir kac saniyeligine sok olmustum
Once sorulari bir calistiralim , ciktilara bakalim , sonrasin da ise ciktilarin nasil olupta boyle sonuclar urettigi ile ilgili hep beraber burda kafa patlatalim
program statikAlistirma; {$APPTYPE CONSOLE} uses SysUtils; type TDosya = Class private FFileName: String; procedure SetFileName(const Value: String); protected public procedure IslemYap();virtual; procedure statikMethod(); property FileName:String read FFileName write SetFileName; End; TXMLDosya = Class(TDosya) private protected public procedure IslemYap();override; End; TCSVDosya = Class(TDosya) private protected public procedure statikMethod(); procedure IslemYap(); End; { TDosya } procedure TDosya.IslemYap; begin Writeln(FileName + ' islem yapiliyor'); end; procedure TDosya.SetFileName(const Value: String); begin FFileName := Value; end; procedure TDosya.statikMethod; begin Writeln('TDosya sinifinin statik methodu'); end; { TXMLDosya } procedure TXMLDosya.IslemYap; begin inherited; Writeln('XML dosya isleniyor'); end; { TCSVDosya } procedure TCSVDosya.IslemYap; begin Writeln('CSV dosya isleniyor'); end; procedure TCSVDosya.statikMethod; begin Writeln('CSV dosyasinin statik methodu'); end; var dosya:TDosya; begin try dosya :=TDosya.Create; dosya.FileName :='deneme'; TCSVDosya(dosya).statikMethod; FreeAndNil(dosya); readln; { TODO -oUser -cConsole Main : Insert code here } except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
soru-1 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TDosya.Create; dosya.statikMethod; FreeAndNil(dosya); readln;
soru-2 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TCSVDosya.Create; dosya.statikMethod; FreeAndNil(dosya); readln;
soru-3 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TCSVDosya; begin try dosya :=TCSVDosya.Create; dosya.statikMethod; FreeAndNil(dosya); readln;
soru-3 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TCSVDosya; begin try dosya :=TCSVDosya.Create; TDosya(dosya).statikMethod; FreeAndNil(dosya); readln;
soru-4 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TCSVDosya.Create; TCSVDosya(dosya).statikMethod; FreeAndNil(dosya); readln;
soru-5 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TXMLDosya; begin try dosya :=TXMLDosya.Create; dosya.statikMethod; FreeAndNil(dosya); readln;
soru-6 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TXMLDosya.Create; dosya.FileName :='deneme'; dosya.IslemYap; FreeAndNil(dosya); readln;
soru-7 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TCSVDosya.Create; dosya.FileName :='deneme'; dosya.IslemYap; FreeAndNil(dosya); readln;
soru-8 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TXMLDosya.Create; dosya.FileName :='deneme'; TDosya(dosya).IslemYap; FreeAndNil(dosya); readln;
soru-9 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TDosya.Create; dosya.FileName :='deneme'; TXMLDosya(dosya).IslemYap; FreeAndNil(dosya); readln;
soru-10 asagidaki sekilde programi calistirirsan ekranda ne yazar ? Nicin?
var dosya:TDosya; begin try dosya :=TDosya.Create; dosya.FileName :='deneme'; TCSVDosya(dosya).statikMethod; FreeAndNil(dosya); readln;
Ellerine sağlık sadettinim. Gayet eğitici ve öğretici bir yazı olmuş. Benim de çok uzun zamandır yazmayı planladığım ama elimin gitmediği pek çok makale var. Bu sorularına bizler en son yanıt verelim. Bakalım bir kaç kişiden başka takip eden varmıymış blogu
Hazır burada iken geçenlerde yaptığım ve bulmakta epey zorlandığım bir hatamı da yazayım, belki birilerinin aynı hataya rast gelmesine de mani olmuş oluruz. Genellikle programlarımda memory leak’lere çok dikkat ederek kod yazarım ama benim de başıma memory leak belası gelmez değilmiş demek ki
Siz siz olun her daim projenin kaynak kodunda ReportMemoryLeaksOnShutDown seçeneğini açıkta tutun ki böcekleri büyüyüp serpilmeden halledebilesiniz
Gelelim küçük örneğimize;
Genellikle bir form oluşturacağım zaman o formun daha önce oluşturulup oluşturulmadığını kontrol etmem. Bunu derleyiciye bırakırım. Kullandığım yöntemi ve hatamı göreceksinizdir muhtemelen.
TForm2 = class(TForm)
private
fAdiSoyadi : String;
public
property AdiSoyadi : String read fAdiSoyadi write fAdiSoyadi;
end;
// Bu formun OnClose’unda Action := caFree ve form2 := nil; olduğunu hayal edin.
uses
unit2;
…
…
procedure TForm1.Button1Click(Sender : TObject);
begin
try
form2.AdiSoyadi := ‘Deneme’;
form2.Show;
except
form2 := TForm2.Create(Application);
form2.AdiSoyadi := ‘Deneme’;
form2.Show;
end;
end;
Yukarıdaki metodolojide; form yok ise hata verecek dolayısı ile except bloğuna sıçrayacak ve hatayı raise ile yeniden tetiklemediğim için formumu düzgün bir şekilde oluşturabilecek ve gösterebileceğim. Ancak; form2.AdiSoyadi atamasını yanlışlıkla try bloğu içinde yaptığım için ve o da nil olan bir nesnenin AdiSoyadi alanına bir şey yazmaya çalıştığı için doğal olarak Access Violation hatası ile karşılaşacağım. Ama burada ilginç olan, programın çıkışında aynı zamanda bir UnicodeString kadarlık memory leak’e de neden olmam. Anlaşılan o ki; hafızada rezervasyon yapılmamış yani nil olan bir nesne referansını kullanarak AdiSoyadi alanına bir şey yazıyor olmaya çalışmam, rastgele bir hafıza bölgesine cidden birşeyler yazıldığının göstergesi. Çünkü stringler referans sayımlıdır ve bu atamadan sonra atanan hafıza bölgesine referansı azaltabilecek herhangi bir referans yok.
Biraz uzatmış olabilirim ama umarım ne demek istediğimi anlatabilmişimdir.
Güel bir tespit olmuş.Teşekkürler…
Object pascal ya da OOP konusunda ince noktalari ogrenmek isteyenler icin acele etmeyelim , ciktilar uzerine yorumlarimizi biraz erteleyelim
OOP ya da Object Pascal ile ilgili bir sertifika icin soru hazirlamam gerekse bu konudan en az 3 soru koyardim sinava
Memory leak olayina gelince ise
1-Bu sekilde bir durumda memory leak olusabilecegi hakkinda jetonum benim de mesajini okuduktan sonra dustu. Dikkat edilmesi gereken bir durum.
2-Benim gibi unutkan arkadaslar ReportMemoryLeaksOnShutdown:=DebugHook<>0; seklinde bir kullanim tercih ederlerse musterilerden “yahu program kapanirken hata veriyor” tarzi geri donusler almayacaklaridir
8 ve 9 hariç tüm sonuçlar beklediğim gibi çıktı. Sınıfların statik metodları, casting işlemleri, overriding, inheritance… Fakat 8. ve 9. sorularda sonuçların ters çıkma sebebini kavrayamadım henüz
TDosya tipinde tanımladım, TXMLDosya olarak create ettim, TDosya’ya cast edip IslemYap çağırdım… Nasıl oldu da TXMLDosya.IslemYap koşuldu?
Aynı şekilde TDosya olarak create edip TXMLDosya’ya cast ettim; nasıl oldu da TDosya.IslemYap koşuldu?.. Tamam, bunu biraz sallayarak açıklayabilirim ( create ettiğin tip vs vs gibi ), ama 8. soruda özellikle TDosya casting işleminden sonra nasıl miras alan sınıfın metodu koşuldu anlayamadım bir türlü ((:
Emeğinize sağlık Sadettin Bey.
Daha önce okumuştum ama kodları ancak test etme fırsatım oldu.
Sonlara doğru biraz şaşırmadım değil
Bu kodu bende gpslerin sunucunda deneyeceğim bende kurtulamadığım bir kapatma hatası alıyorum. Belki işe yarar.
Soru 11:
var dosya: TDosya;
begin
try
dosya := TXMLDosya.Create;
dosya.FileName := ‘deneme’;
TCSVDosya(dosya).IslemYap;
FreeAndNil(dosya);
readln;
Soru:12
var dosya: TDosya;
begin
try
dosya := TCSVDosya.Create;
dosya.FileName := ‘deneme’;
TXMLDosya(dosya).IslemYap;
FreeAndNil(dosya);
readln;