JavaScript Temelleri

Bölüm 15

Kullanıcı Tanımlı Nesneler

Bölüm 15 Sayfa 4

15.4 -Üst Sınıf / Alt Sınıf - Nesne Hiyerarşisi

Nesne sisteminde üstSınıf, üst sınıf olarak nitelendirilen bir sınıfın özelliklerinin, alt sınıf olarak nitelendirilen bir başka sınıfa aktarılmasıdır. JavaScript programlama dili, üstSınıfı destekler, fakat üstSınıfla ilgili olan çalışmalar, kullanıcılar tarafından tanımlanmalıdır.

JavaScript programlama dilinde, nesne hiyerarşisi iki türlü gerçekleştirilebilir. İlki yapılandırıcı fonksiyonların birbirini çağırması yöntemidir. Bu yöntem, dinamik üstSınıfı, yani, hiyerarşi oluşturulduktan sonra, üst sınıfta yaratılacak yeni bir özelliğin alt sınıflara aktarılması sağlamaz. Ama bu kullanıcı tarafından tanıtılabilir. Ayrıca bu yöntem, prototip transferi yöntemi ile gerçekleştirilen gerçek dinamik prototip zincirinin desteklemediği, birden çok üst sınıftan üstSınıfın yani çoklu üstSınıfın da gerçekleşebilmesine olanak sağlar.

İkinci yöntem, prototip transferi ile protip zincirinin oluşturulmasıdır. Bu yöntem, dinamik üstSınıfı sağlar, fakat çoklu üstSınıf desteklenmez. Bunun için, ek düzenlemeler yapılması gerekir. Her iki yöntem de, ayrı ayrı incelenecektir.

15.4.1 - Yapılandırıcı Fonksiyonlardan Yararlanılarak Gerçekleştirilen Üst Sınıf / Alt Sınıf Hiyerarşisi

Yapılandırıcı fonksiyonlaran yararlanılarak gerçekleştirilen üstSınıf, prototip zinciri yaratmaz fakat bu yöntem, birden çok sınıftan kaynaklanan özelliklerinin üstSınıfla kazanımına olanak sağlar. Bu konuda bir JavaScript programı ve bağlantılı olduğu uygulama sayfasında verdiği sonuç, aşağıda görülmektedir:

...
function Üretim(nr) {
this.seriNumarası = nr || 0 ;
}

function Yapım(materyel, şekil) {
this.malzeme = materyel || '';
this.kutuŞekli = şekil || '';
}


function Kare(seriNr, materyel, kenar) {
this.en = kenar || 0;
this üstSınıf1 = Üretim;
this üstSınıf1(seriNr);
this üstSınıf2 = Yapım;
this üstSınıf2 (materyel, 'Kare');

this.hacım =function () {

return Math.pow(this.en, 3);
}
}

function Dikdörtgen(seriNr, materyel, eni, boyu, yüksekliği) {
this.boy = boyu || 0;
this.yükseklik = yüksekliği || 0i;
this.üstSınıf = Kare;
this.üstSınıf(seriNr, materyel, eni);
this.kutuŞekli = 'DikDörtgen';
this.hacım =function () {

return this.en * this.boy * this.yükseklik;
}
}


function çokluKalıtım() {

var kutu24 = new Kare(34688, 'Karton', 12), kutu25 = new Dikdörtgen(45786, 'Teneke', 10, 10, 10); 

sonuçYaz('kutu24 Özellikleri =  ', kutu24.seriNumarası + ' ' + kutu24.kutuŞekli + ' ' + kutu24.malzeme + ' ' + kutu24.hacım() , 'b15.4.1-uyg-1-sonuç-1');
sonuçYaz('kutu25 Özellikleri =  ', kutu25.seriNumarası + ' ' + kutu25.kutuŞekli + ' ' + kutu25.malzeme + ' ' + kutu25.hacım() ,  'b15.4.1-uyg-1-sonuç-2');

}
...
		

Program Sonucu :

kutu.24 Özellikleri : 34688 Kare Karton 1728

kutu.25 Özellikleri : 45786 Dikdörtgen Teneke 1000

Alınımış olan sonuçların iyi anlaşılması için, programın adım adım izlenmesi ve açıklanması yararlı olabilir. Programda ilk fonksiyonlar olan Üretim() ve Yapım() fonksiyonları, yapılandırıcı fonksiyonlardır fakat bu fonksiyonların amacı, örnek üretmek değildir. Bu iki fonksiyon, birer üst sınıf olarak özelliklerini alt sınıflara aktarmak amacı ile oluşturulmuştur.

Bundan sonraki Kare() fonksiyonu ise gerçek bir yapılandırıcı fonksiyondur ve bu yapılandırıcı fonksiyon, üretilen kare şeklindeki kutuların kaydedilmesi amacı ile yapılmıştır. Kare geometrik şeklinin tüm kenarları birbirine eşittir. Bu şekil, en az boyut özelliklerine sahip olduğu için hiyerarşide üst sınıflara en yakın düzeyde alt sınıf olarak seçilmiştir. Kare kenar boyutu Kare() yapılandırıcı fonksiyonunun tek boyut argümanı ile girilmektedir. Bu argüman, ilginç olarak en adı verilmiş olan bir özelliğe atanmaktadır. Bu özelliğin niçin en olarak adlandırıldığı biraz sonra görülecektir. Bundan sonra hacım olarak adlandırılmış olan bir özelliğin değerine, bir anonim (isimsiz fonksiyon) atanmaktadır. Doğal olarak istendiğinde bu fonksiyon, bir dış fonksiyon olarak tanımlanabilir ve referansı yapılandırıcı fonksiyona aktarılabilirdi. Bu konuda seçim, programcıya kalmıştır. Bundan sonra, Kare() yapılandırıcı fonksiyonunda yeni bir üstSınıf1 özelliği tanımlandığı ve bu özelliğe Üretim fonksiyonunun referansının atandığı görülmektedir. Kalıtımı sağlayan işlemi bu atama başlatmaktadır. İkinci aşamada bu özelliğe atanmış olan fonksiyonun çalıştırıldığı görülmektedir. Bu aşama ile ilk alt sınıf oluşturlması gerçekleştirilmekte ve Üretim() üst sınıfının tüm özellikleri, Kare() alt sınıfına aktarılmakta ve üstSınıfla aktarılan seriNumarası özelliğine, Kare() yapılandırıcı fonksiyonunun seriNr argümanı atanmaktadır.

Kare() yapılandırıcı fonksiyonunda bundan sonra, yeni bir üst sınıf tanımı yapılmış, bu sefer Yapım() sınıfı, Kare nesne sınıfı için üst sınıf olarak belirtilmiştir. Buradan üstSınıf ile aktarılan malzeme özelliğinin varsayılan değeri olarak Kare() yapılandırıcı fonksiyonunun materyel argümanı değeri atanmıştır. Yine üst Yapım sınıfından kalıtımla gelen kutuŞekli özelliğinin varsayılan değeri yerine Kare seklinin sabit olan geometrik şekli olan 'Kare' sabit değeri atanmıştır. Bu durumda, Kare sınıfı, iki üst sınıftan özellik alır duruma gelmiş ve çoklu kalıtım olayı gerçekleşmiştir.

Bir sonraki, Dikdörtgen() yapılandırıcı fonksiyonunda ise, çok daha ilginç yöntemler uygulanmıştır. Bu fonksiyonun seriNr, materyel, eni, boyu, yüksekliği olmak üzere, beş tane argümanı vardır. son iki argüman üst sınıflardan kalıtımla aktarılmayan özelliklere aittir ve hemen atanmaktadırlar. Bundan sonra, Dikdörtgen sınıfının bir düzey üst sınıfı olarak Kare sınfının tanımlanması yapılmaktadır. Kare üst sınıfından seriNumarası, malzeme ve kutuŞekli özellikleri, Kare sınıfında atanmış değerleri ile, Dikdörtgen sınıfına kalıtımla aktarılacaklardır. Bu değerlere Dikdörtgen sınfının özellik değerlerinin atanması için , üstSınıf() fonksiyonuna Kare() yapılandırıcı fonksiyonunun referansı atanmıştır. Artık üstSınıf() fonksiyonu, Kare() yapılandırıcı fonksiyonunu gibi hareket etmekte ve burada this saklı sözcüğü artık Dikdörgen nesne sınfıını işaret etmektedir. Bu şekilde, üstSınıf() fonksiyonunun argümanlarına, aynı Kare() yapılandırıcı fonksiyonunun sırasında, sıra ile, Dikdörtgen() yapılandırıcı fonksiyonun seriNr, materyel ve eni argümanları atanmaktadır. Burada, Kare sınfında kenar uzunluğu için en özellik adının niçin seçilmiş olduğu da ortaya çıkmaktadır. Kare ve Dikdörtgen sınıfında aynı özelliği belirten özellik isimlerinin aynı olması için, Kare sınıfında kenar uzunluğu özelliği en olarak adlandırılmış ve bu özelliğin değeri, dikdörtgen sınıfında yeniden tanımlanmıştır. Bu yönteme, özellik değerine bindirme adı verilir ve hiyeraşik yapılanmada çok önemlidir. Bu şekilde aynı işlevi gören özelliklere her sınıfta ayrı isimler verimesi gerekmeyerek, programın kolay izlenebilmesi ve bakımı sağlanmış olmaktadır.

Dikdörtgen sınıfı yapılandırıcı fonksiyonunda gerçekleşen önemli yapılanmalardan birisi de, üst düzey Kare sınıfından gelen, fakat hiçbir yapılandırıcı fonksiyonun argüman listesinde bulunmayan, kutuŞekli özelliğine Dikdörtgen sınıfı için özel değerin atanmasıdır. Burada kutuŞekli özelliği, bir üst düzey Kutu sınıfından kalıtımla fakat üst Kutu sınıfında atanmış olduğu 'Kare' öntanımlı değeri ile gelmektedir. Hiçbir argüman listesinde olmadığı için, bu özelliğin değerine, Dikdörgen sınfında açık (explicit) olarak bindirilmekte ve dikdörgen geometrik seklinin sabit değeri olan 'Dikdörtgen' değeri atanmaktadır.

Dikdörtgen sınıfına, bir düzey üst sınıf olan Kare sınıfından kalıtımla gelen hacım() metodunun içeriği, Dikdörgen sınıfı için uygun olmadığından, bir alt düzey alt sınıf olan Dikdörtgen sınıfında içeriği değiştirilmiştir. Buna metot bindirme adı verilmektedir. Hiyerarşik yapılanmalarda metot bindirmeleri çok önemlidir. Her sınıf için aynı isim fakat farklı içerikte metotlatla çalışma olanağını vermekte bu şekilde aynı işlevi yapan metotların her sınıfta farklı olabilecek isimlerinin tek ve tanınabilen bir isim olması sağlanabilmektedir.

Yukarıdaki uygulamanın sonuçlarının incelenmesinden tüm değerlerin istendiği gibi, sınıf özelliklerine atanabildiği ve metotların her sınıfta gerektiği gibi çalıştığı anlaşılmaktadır. Özetle, yapılandırıcı fonksiyonlarının birbirleri içinden çağrılması yöntemi ile oluşturulan sınıf hiyerarşisi iyi çalışmaktadır ve biraz sonra görülecek protoip transferi yöntemi ile gerçekleştirilemeyen çoklu kalıtım da bu yöntemle gerçekleştirilebilmektedir.

Yukarıdaki uygulamada hiyeraşinin oluşturulması ve nesne sınıf örneklerinin başarı ile yaratılması ile birlikte sistemin programlama aşaması tamamlanmış ve veri girişi aşaması başlamış olmaktadır. Veri girişi programları, hiyerarşik nesne yapılanması sisteminin, belirlenmiş olan veri yapılarına dayanır. Bir kez belirlendikten ve sistemin yapılanması tamamlandıktan sonra, veri girişi aşamasına geçildikten sonra, asla veri yapılarında değişiklik yapılamaz.

Veri sişstemleri, az sayıda nesne örneği yaratılması için tasarlanmaz. Nesne örnekleri, dizilerin elemanları olarak oluşturulur. Veri dizileri ileride göreceğimiz gibi disklerde saklanır. Verilere uygun programlarla erişilir ve gerekli bilgiler alnır.

Veri giriş programları, verilerin yapılarına uygun olan veri girişleri , verilerin dizilerde düzenlenmesi, disk dosyalarının yönetimi, girilmiş verilerin düzeltilmesi, silinmesi, görüntülenmesi ve baılı çıktılar (printout) alınması programlarını içerir. Eğer veriler bir veri temeline yerleştirilecekse, veri temeline yerleştirme programlar da bu aşamada düzenlenir. Sonunda üretinm aşamasına geçilebilir.

Tüm kontroller tamamlandıktan sonra veri Üretim aşamasına geçilir. Bu aşamada veriler girilir ve disk veya naşka depolama alanlarında saklanılır. Verilere ikinci aşamada geliştirilmiş programlar kullanılarak erişilir, baskılı veya görüntü listeleri alınır.

Üretim aşamasındaki sistemin sonsuza kadar bu şekilde devam edileceği ve değiştirilmeyeceği varsayılır. Aslında gerçek böyle değildir. Veri sisteminin eskimesi diye bir kavram vardır. Üretim aşamasında, sistem çalışırken, kullanıcılar veri yapısında bazı eksiklikler olduğunu, istedikler bazı bilgilerin veri temelinde bulunmadığını farkederler ve veri yapılarına yeni özellikler eklenmesini isteyebilirler. Örnek olarak, yukarıdaki uygulamada üretilen kutuların renginin de kaydedilmesini isteyebilirler. Bazen bu baskılar bunaltıcı olur ve acil çözüm aranır. Aslında acil çözüm yoktur, değişimin de bir sistematiği vardır ve buna uyulmadığında sorunlar yaşanır.

Bazı durumlarda, üst sınıflardan birinin prototipine yeni özellikler eklenmesi önerilir. Aslında, bu en kötü öneridir. Bu çalışmada, öntanımlı olsun, kullanıcı tanımlı olsun, hiçbir nesne sınıfının tanımlamış prototipini değiştirmeyi önermiyoruz. Bu işlemin yan etkileri çok olumsuz olabilir.

Herşeyden önce, yukarıdaki uygulamada olduğu gibi, nesne sınıflarının yapılandırıcı fonksiyonların birbirleri içinden çağrılması ile oluşturulan hiyerarşik yapılanmada, sınfların prototipleri birbirinden bağımsızdır ve sınıflar arasında kurulmuş olan alt sınıf/üst sınıf ilişkisi sınıf prototipleri yolu ile kurulmamamıştır. Bu nedenle, üst sınıfta yeni tanımlanmaış bir özelliğin alt sınıfa kalıtımla aktarılması olanağı yoktur. Bira ileride incelenek olduğu gibi, Bu durumun düzeltilmesi, prototiplerin basit bir ifade ile birbirlerine ilişkilendirilmesi ile çözülür. Bu şekilde, bundan sonra yaratılacak nesne sınıf örneklerinde bu yeni özellik bulunacaktır, fakat oluşturulmuş eski örnekler, bir disk üzerinde saklanıyorsa, bu yapı değişikliği onların yapısını uyumsuz duruma getirmiş olacaktır.

Yukarıdaki uygulamada belirtilmiş olan hiyerarşik yapılanmanın, prototiplerin de birbirlerine ilişkilendirilmesi ile pekiştirilmesi ve yapılanma tamamlandıktan sonra üst sınıfa eklenen bir kutuRengi özelliğinin alt sınıfa kalıtımla aktarılması, aşağıda görülen JavaScript programında gerçekleştirilmiş ve bu programın bağlantılı olduğu sayfada vermiş olduğu sonuç, aşağıda görüntülenmiştir:

...
function Üretim(nr) {
this.seriNumarası = nr || 0 ;
}

function Yapım(materyel, şekil) {
this.malzeme = materyel || '';
this.kutuŞekli = şekil || '';
}

Kare.prototype = new Yapım;

function Kare(seriNr, materyel, kenar) {
this.en = kenar || 0;
this üstSınıf1 = Üretim;
this üstSınıf1(seriNr);
this üstSınıf2 = Yapım;
this üstSınıf2 (materyel, 'Kare');

this.hacım =function () {

return Math.pow(this.en, 3);
}
}

Dikdörtgen.prototype = new Kare;

function Dikdörtgen(seriNr, materyel, eni, boyu, yüksekliği) {
this.boy = boyu || 0;
this.yükseklik = yüksekliği || 0;
this.üstSınıf = Kare;
this.üstSınıf(seriNr, materyel, eni);
this.kutuŞekli = 'DikDörtgen';
this.hacım =function () {

return this.en * this.boy * this.yükseklik;
}
}

Yapım.prototype.kutuRengi = 'Beyaz';


function çokluKalıtım() {

var kutu24 = new Kare(34688, 'Karton', 12), kutu25 = new Dikdörtgen(45786, 'Teneke', 10, 10, 10); 

sonuçYaz('kutu24 Özellikleri =  ', kutu24.seriNumarası + ' ' + kutu24.kutuŞekli + ' ' + kutu24.malzeme
 + ' ' + kutu24.kutuRengi + ' ' + kutu24.hacım() , 'b15.4.1-uyg-2-sonuç-1');
sonuçYaz('kutu25 Özellikleri =  ', kutu25.seriNumarası + ' ' + kutu25.kutuŞekli + ' ' + kutu25.malzeme
 + ' ' + kutu25.kutuRengi + ' ' + kutu25.hacım() , 'b15.4.1-uyg-2-sonuç-2');

}
...
		

Program Sonucu :

kutu.24 Özellikleri : 34688 Kare Karton Beyaz 1728

kutu.25 Özellikleri : 45786 Dikdörtgen Teneke Beyaz 1000

Yukarıdaki uygulamada prototip zincirinin oluşturulduğu ve üst sınıf olan Yapım sınıfının prototipine eklenen kutuRengi özelliğinin kalıtımla alt düzey sınıflarına geçtiği görülmektedir. Burada sadece kutuRengi özelliğinin öntanımlı değeri kalıtımla aktarılmaktadır. Gerçek kutuRengi değerlerinin girilebilmesi için yapılandırıcı fonksiyonlarda değişiklik yapılması gerekmektedir.

Yapılandırıcı fonksiyonların yeniden yapılanması sırasında, yeni eklenen kutuRengi özelliğinin de Yapım sınıfının yapılandırıcı fonksiyonuna eklenmesi doğru davranış olacaktır. Ayrıca, her zaman prototip zincirininde oluşması sağlanmalıdır ki, sistem alt/üst sınıf düzenlemesinden haberli olsun ve üst düzeyde yeni eklenen bir özellik, alt düzeye kalıtımla aktarılabilsin. Bu düzenleme, aşağıda görülen JavaScript programında gerçekleştirilmiş ve bu programın bağlantılı olduğu uygulamada sayfasında verdiği sonuç aşağıda görüntülenmiştir:

...
function Üretim(nr) {
this.seriNumarası = nr || 0 ;
}

function Yapım(materyel, şekil, renk) {
this.malzeme = materyel || '';
this.kutuŞekli = şekil || '';
this.kutuRengi = renk || '';
}

Kare.prototype = new Yapım;

function Kare(seriNr, materyel, renk, kenar) {
this.en = 0 || kenar;
this üstSınıf1 = Üretim;
this üstSınıf1(seriNr);
this üstSınıf2 = Yapım;
this üstSınıf2 (materyel, 'Kare', renk);
this.hacım =function  {

return Math.pow(this.en, 3);
}
}

Dikdörtgen.prototype = new Kare;

function Dikdörtgen(seriNr, materyel, renk, eni, boyu, yüksekliği) {
this.boy = boyu || 0;
this.yükseklik = yüksekliği || 0;
this.üstSınıf = Kare;
this.üstSınıf(seriNr, materyel, renk, eni);
this.kutuŞekli = 'DikDörtgen';
this.hacım =function () {

return this.en * this.boy * this.yükseklik;
}
}


function çokluKalıtım() {

var kutu24 = new Kare(34688, 'Karton', 'Mavi', 12), kutu25 = new Dikdörtgen(45786, 'Teneke', 'Metalik Kırmızı', 10, 10, 10); 

sonuçYaz('kutu24 Özellikleri =  ', kutu24.seriNumarası + ' ' + kutu24.kutuŞekli + ' ' + kutu24.malzeme
 + ' ' + kutu24.kutuRengi + ' ' + kutu24.hacım() , 'b15.4.1-uyg-3-sonuç-1');
sonuçYaz('kutu25 Özellikleri =  ', kutu25.seriNumarası + ' ' + kutu25.kutuŞekli + ' ' + kutu25.malzeme
 + ' ' + kutu25.KutuRengi + ' ' + kutu25.hacım() , 'b15.4.1-uyg-3-sonuç-2');

}
...
		

Program Sonucu :

Bu son düzenleme , yeni eklenen kutuRengi, özelliğinin Yapım() fonksiyonuna alınması ile yapılandırıcı fonksiyonların biribirlerini çağırması yöntemi ile hiyerarşinin oluşturulmasını yine sağlamış, fakat her olasılığa karşın, prototip transferi yöntemi ile de alt/üst sınıf ilişkisini, protip zincirini kurarak da oluşturmuştur. Hem yapılandırıcı fonksiyonlar, hem de prototip transferi yöntemini birlikte içerdiğinden bu tip bir hiyerarşi kurulması belki de en sağlam hiyerarşi oluşturma yöntemidir.

Bu son program sadece kalıtım problemini çözmüş olmaktadır. Bunun dışında, veri giriş fonksiyonlarının yeni veti yapısına göre yeniden düzenlenmesi ve eskiden yaratılıp disk üzerinde saklanılan eski nesne örneklerinin yeni veri yapısına göre yeniden düzenlemesi sorunları henüz çözüm beklemektedir. Veri yapısının değişmiş olması nedeni ile, disk üzerinde dosyalarda kayıtlı büyük sayıda eski veri, sınıfsız kalmış ve birer nesne literali niteliğine dönüşmüşlerdir. Bu yerilerin yeni girilen veriler ile uyumunu sağlamak, yani eski verileri de yenilenmiş hiyerarşik sınıflardan birinin örnekleri haline getirmek için, uyum fonksiyonları yazılıp uygulanmalıdır.

Bütün bu sorunlar, oluşmuş ve veri üretimi aşamasında olan, büyük çapta veri girilimiş bir sistemin yapısını bozmanın ne kadar yanlış olduğunu açıkça ortaya koymaktadır. Burada incelenen örneklerde bile, ikinci örnekte eklenen bir tek özellik bile, yapılandırıcı fonksiyonların yeniden yazılarak son uygulama daki hale getirilmeleri gereğini doğurmaktadır.

Bu durumda çalışan bir sitemde veri yapısında değişiklik yapılması gerekirse, sisteme eklemeler yapmak yerine yeni bir sistem oluşturulmalıdır. Yeni veriler bu yeni sistemle girilmeye devam edilirken, eski üretimiş verileri, uyum programları ile yeni veri yapısına uyumlu hale getirilmelidir. En sonunda, herşey çalışır hale gelince, yeni sistemin adı eski sistemin adına dönüştürülmelidir. Bu şekilde veri yapısının sorunsuzca güncellenmesi sağlanabilecektir.

Valid XHTML 1.1