> Delphi > Delphi.NET’in Yeni Oyuncağı “Class Helper”

Delphi.NET’in Yeni Oyuncağı “Class Helper”

.Net ortamı için sadece Delphi’de bulunan bir nesne özelliği ile tanışalım bugün, Class Helper(Sınıf Hizmetçisi, Yardımcısı, ya da ne isim verirseniz.). C# kullanıcıları, 2.0 sürümü ile benzer bir tip olan "Partial Type" ile tanıştılar. Ama partial tipler hali hazırda derlenmiş kodlar üzerinde işlem yapamazlar. Ama class helper’lar yapabilirler! Yani derlenmiş bir assembly’ de bulunan bir sınıf üzerine de class helper yazılabilir.

Nedir bu Class Helper? Yenilir mi, içilir mi, grameri nasıldır, ne işimize yarayacak? Bütün bu soruların cevaplarını bu kısa makalemizde vermeye çalışacağız.

Giriş

Hemen konuya girelim. Class Helper -yada sınıf hizmetçisi, ya da yardımcısı-, kendisinde bulunan bütün alanlarıyla, yardımcı olduğu sınıfı genişleten bir yapıdır, şeklinde tanımlanabilir. Class helper, mevcut bir sınıfı değiştirmeden veya bu sınıftan yeni bir sınıf türetmeden, bu sınıfa yeni özellikler, metodlar katmaya yarar. Böylece mevcut sınıfta hiç bir müdahaleye gerek kalmadan ve yeni bir sınıf türetmeden, mevcut sınıfımız istediğimiz şekilde şekillenecektir.

Borland bu yapıyı, VCL kütüphanesini .NET ortamına geçirirken ihtiyaç duymuştur. Çünkü Win32’de tanımlanmış olan bir sınıf, hem .Net’i desteklemesi lazım hem de mevcut yapısını koruması lazım. İşte class helper, nesne programlamaya böyle bir esneklik getirmiştir.

Grameri

Şimdi bu yapının grameri nasıldır ona bakalım:



		

Ardından bu sınıfımızdan bir nesne oluşturalım:



		

Farkında iseniz TSinif adlı sınıfımızda "BirFonksiyon" isimli bir fonksiyon bulunmamakta. Ama bir class helper tanımlayarak, olmayan bu fonksiyonu sınıfımıza ekledik.

Yanlış Kullanımlar ve Sınırlar

Nasıl ki programlamada her tekniğin bir yapabildiği olduğu gibi, tekniğe ters olan bazı şeyler de vardır. İlk önce yanlış kullanımlara bakalım:

  • Mevcut .NET sınıflarını, kod tanımlamasını değiştirmeden genişletmeye çalışmak.
  • Mevcut .NET sınıflarını onlardan miras almadan genişletmeye çalışmak.
  • Sealed sınıfları genişletmeye çalışmak. (Sealed sınıflar, sınıf hiyerarşisinde kısır sınıflar olarak bilinirler. Yani sealed sınıflardan herhangi bir başka sınıf türetilemez.)
  • Büyük bir sınıf tanımlamasını birden fazla kaynak dosyaya rast gele bir şekilde bölmek.

Her ne kadar bunları yapabilseniz de, tavsiye edilmez ve yanlış kullanım kategorisindedir. Özellikle bir sınıf sealed olarak tanımlanmışsa, bunun elbette bir sebebi vardır. Bunu genişletmek, istenmeyen sonuçlara sebebiyet verebilir.

Yapamayacağınız şeyler ise şunlardır:

  • Bir class helper, genişlettiği sınıfın "strict private" olarak tanımlanmış alanına erişemez. Gerçi Delphi programcıları için bu, ne kadar doğru bir sınırlandırma olduğu tartışma konusu olmuştur ve olmaktadır.
  • Bir class helper, genişlettiği bir sınıf için interface tanımlayamaz.
  • Bir class helper için başka bir class helper tanımlanamaz.

Tabi yapılan en büyük yanlışlıklardan bir tanesi de, class helper’ları ayrı dosyada tanımladıktan sonra bunları ana sınıfın unitinde implementation alanında değil de interface alanında uses’a eklemek olacaktır. Bu da çapraz başvurudan dolayı hataya sebep olacaktır. Çünkü eklediğiniz helper unitinde interface alanında zaten uses kısmında ana sınıfın uniti eklenmiş durumdadır. Bu esasen class helper’larla alakalı bir hata olmadığından yukarıdaki maddelere eklemedim.

Faydaları

Eğer birden fazla kişi aynı sınıf üzerinde çalışıyorsa, class helper’lar gerçekten çok işe yaramaktadır. Class helper kullanılmadığında, bir çok programcının yazdığı sınıfları bir sınıfta birleştirmek için bir kişinin uğraşması gerekmektedir. Bunu yapacak kişi de her yazılan sınıftaki özellik ve metodlara aşina olması şarttır. Class helper kullanıldığında, her programcı, sınıf içinde kendine ayrılmış kısım ile ilgili bir class helper yazar ve bir unit’e kaydeder. Geriye kalan sadece bunları uses’a eklemek ve derlemektir. Derleme işleminde, derleyici bu class helper’ları mevcut sınıfa ekleyerek birleştirip bir sınıf yapacaktır.

Eğer sınıfınız bazı özel araçlar ile oluşturulmuş ise, class helper kullanarak bu oluşturulmuş olan kodda değişiklik yapmanıza gerek kalmayacaktır. Çünkü bu araç ile bir daha kodu üretmeniz gerektiğinde yazdığınız değişikliklerin kaybolmasına sebep olacaktır. Class helper kullanmadan bu tarz bir koda müdahale etmeniz zordur.

Düşünün ki, ürettiğiniz yazılımın bir kaç versiyonu olacak. Mesela profesyonel, standart, temel(basic) gibi versiyonlarınız olacak. Profesyonel’de olan özellikler standart’a göre daha fazla olacak. Standartta olan özellikler de temel versiyona göre daha fazla olacak. Class helper kullanmadığınızda bu versiyonları oluşturmak için ayrı ayrı sınıflar oluşturmalısınız. Bu durumda temel sınıftaki bir özellik veya metodun değişmesi, bug’ların giderilmesi gibi işlemlerde aynı şeyleri hepsi için tek tek yapmalısınız. Birini birinden türetseniz dahi, mesela temel sınıfı ata sınıf kabul edip, diğerlerini ondan türetseniz dahi bu işinizi görmeyecek hatta daha da sıkıntılı bir duruma sokabilecektir. Çünkü nesnelerin kullanımı esnasında, ister istemez bir çok sorunla yüzleşeceksiniz. Bu sorunları çözmek için ek arayüzler ve sınıflar tanımlamak zorunda kalabileceksiniz. Halbuki class helper kullanıldığında sadece en temel olan sınıfı yazarsınız ve diğer sınıfları class helper olarak tanımlarsınız. Böylece mesela programın temel sürümünü derlemek için profesyonel ve standart class helper’larını projeden çıkarmanız yeterli olacaktır. Profesyonel sürümünü derleyeceğinizde ilgili class helper’ı projenize eklersiniz ve her şey bir çırpıda halledilmiş olur.

Belki faydaları daha da artırılabilir. Ama kafanızda bir fikir oluşması için bunlar yeterli.

(Güncelleme): Class Helper Önceliği

Anlatmayı unuttuğum bir kısım şimdi aklıma geldi 🙂

Diyelim ki şöyle bir sınıf ve class helper olsun:



		


Gördüğünüz gibi hem sınıfta hem de helper sınıfta da aynı isimde bir metod var. Ama sınıfta private olarak tanımlanmış bir metod, helper’da public olarak tanımlanmıştır. Peki burada hangisi geçerlidir? "MesajGoster" metodu tetiklendiğinde hangi metod çalıştırılacaktır? Aşağıdaki koda bakalım:



		


TSinif’ ta bulunan "BirSeylerYap" metodumuzu bu şekilde yazdık. BirSeylerYap metodu çalıştığında, "MesajGoster" metodunu çağıracak. İşte burada çağrılacak olan daima önceliği fazla olan helper sınıftır. Yani burada TSinif.MesajGoster değil, TSinifHelper.MesajGoster metodu çağrılacaktır. Yani öncelik daima helper sınıfa aittir.

Peki iki helper sınıf arasındaki öncelik neye göre belirlenir? Mesela yukarıdaki sınıfa ve helper’a ek olarak şunu da yazsa idik:



		


TSinif isimli sınıfımızın MesajGoster metodu çağrıldığında hangi metod çağrılacaktır?

Bundan önce class helper’ların daima sınıflardan öncelikli olduğunu gördük. Bu yüzden sınıfı eliyoruz. Diyelim ki TSinifHelper , TSinifHelper2’den daha önce yazılmış, yani daha yukarıda yazılmış. Bu durumda hangisi en sonra ya da en altta tanımlıysa onun sözü geçer. Yani en son tanımlanan helper daha önceliklidir.

Bir öncelik daha kafamızı karıştırabilir. Diyelimki TSinifHelper, untHelper1 adlı dosyada ve TSinifHelper2 ise untHelper2 adlı dosyada. Bu durumda hangisi daha öncelikli olacak? Bu öncelik değeri, aslında bir önceki ile aynı mantıkta. Hangisi uses kısmında en sonda ise o önceliklidir.

Sonuç

Bence, Delphi.NET ile birlikte gelen en iyi özelliklerden birisi class helper’lar. Özellikle takım çalışmasında büyük bir kolaylık sağlıyor. Sınıfın bir kısmını bir kişi, diğer tarafta sınıfın diğer kısmını yazan kişilerden habersiz görevini yerine getirebiliyor. Belki ilk başta klasik sınıf bilgimizden biraz garip gelebiliyor ama kullandıkça, ne kadar yararlı olduğunu görebiliyoruz.

Sorularınız olduğunda buradaki yorum kısmına ya da delphiturkiye forumlarında Delphi.Net kısmına iletebilirsiniz.

Kolay gelsin.

» Tags: , , , ,

6 Comments

  • At 2007.08.01 20:26, t-hex said:

    Aslında C# 2.0’daki partial classlar değilde C# 3.0’daki Extension Methods buna benzer bir işlev sağlıyor. Gerçi benim bildiğim kadaryla Extension method yazarken sınıf belirtilmiyor, derleyici uygun metodları kendisi seçiyor.

    public static class Extensions
    	{
    		public static T[] Slice(this T[] source, int index, int count) {
    			if (index
    

    • At 2007.08.02 11:59, burhan baraklı said:

      Makaleleriniz için teşekkür ederim.

      • At 2007.08.02 15:49, Fatih Tolga Ata said:

        Bildiğim kadarı ile Extension Methods sadece yeni metodlar eklemek için kullanılıyor. Class helper’lar ayrıca property, alan ve class static alanlar eklenmesine de izin veriyor. Ancak Extension Methods ile partial birlikte kullanıldığında aynı etkiyi yakalayabilirsiniz diye biliyorum, yanlış olmasın.

        Yorumlarınız için ben teşekkür ederim.

        • At 2007.09.07 18:55, Memik YANIK said:

          Fatih merhaba;
          Makalelerini beğenerek okuduğumu bilmeni isterim. Hepsi birbirinden yararlı bilgiler içeriyor. Teşekkürler, eline sağlık..

          • At 2007.09.13 00:17, Fatih Tolga Ata said:

            Sağolun Memik bey… Sizin fikirleriniz bizim için gerçekten önemli. Delphi’yi sizin kitaplarınızla öğrendik ve bu günlere geldik. Sizler de sağolun.

            • […] Buradaki makalede ayrıntılı olarak işlenmiştir: http://www.diyezon.com/?p=50 […]

              (Required)
              (Required, will not be published)