Javascript hep gelişmekte olduğunu belirtmiştik. İlk Javascript versiyonları temel nesneye yönelik konularını desteklemiyordu. Daha sonrası, prototype-based inheritance kullanarak sınıf yaratmaya izin verdi. En sonunda ES6 ile beklenen oldu ve class konusu Javascript dünyasına tam anlamı ile geldi. Bu bölümde birçok programlama dili için standart olmuş “Class” konusu üzerinedir.
Doçentlik sınavında “Javascript nedir?” diye basit bir soru gelmişti. Temel çalışmasını anlatmış ancak dilin object-based, inheritance ve polymorphism içermediğini bilememiştim(!). Object-based ne olduğunu bilmiyorum ancak dolaylı yoldan inheritance ve polymorphism içerdiğini söylemiştim. Java ile karıştırdığım iddia edilmişti. Benim için “Dünya dönüyordu…”. Prototype üzerinden kullanılabiliyordu, ES6 ile direkt class geldi. O gün kaldım, küsmedim; çalışmaya, bu hızla gelişen dünyayı çözmeye devam dedim. Şimdi asıl konumuza gelelim.
Öncelikle, bu bölümü anlayabilmeniz için nesne yönelimli programlama konusunda bilginiz olmalıdır. Örnekte iki sınıf yaratıp ve iki sınıf arasında bir kalıtım oluşturacağım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class kisi { constructor(ad) { this.ad = ad; } merhaba() { return 'Merhaba ben ' + this.ad + '.'; } } class futbolcu extends kisi { merhaba() { return super.merhaba() + ' Ben futbolcu.'; } } let messi = new futbolcu('Messi'); console.log(messi.merhaba()); |
this o sınıfın içeriği özelliklere bağlanmak için kullanılır. Constructor içinden this.ad ile değişken oluşturulup programın herhangi bir yerinden kullanılabilir. Kısacası, diğer programlama dillerinde olduğu gibi bir değişken tanımlaması yapmadan ve değişkenin erişim belirtecini (public, private) belirtmeden kullanmak mümkündür. constructor, nesne oluşturulurken çalışan ilk fonksiyondur ve örnekte ad değişkeni nesne oluşturulurken almak için kullanılır. Merhaba fonksiyonu this.ad değişkenindeki değeri gösterir. extends sayesinde kisi sınıfının tüm özellikleri futbolcu sınıfı tarafından kullanılabilir. Ancak, üst sınıftaki merhaba fonksiyonunun yerine yeni bir fonksiyon oluşturmak isteyebilirsiniz. Bu işleme fonksiyon aşırı yüklemesi (function overloading) denir. Bir anlamda kisi sınıfındaki merhaba fonksiyonu geçersiz kılınmış olur. Ancak, yine de kisi sınıfı içindeki merhaba’ya alt sınıftan (futbolcu) içinden “super” anahtar kelimesi ile ulaşabilirsiniz. This bütünü işaret ederken super ana sınıfı (kisi) işaret eder. This.merhaba() deseydik, sınıf ana sınıf mı alt sınıf mı kullanacağını karıştırdı. Son aşamada, sınıftan nesne oluşturduk. İstersen üst sınıftan da nesne oluşturabilirsiniz ancak ben futbolcu sınıfını tercih ettim. Messi dünyada gelirken adını kisi constructor’ından aldı. Merhaba fonksiyonu çağrıldığında ise futbolcu merhaba fonksiyonu kisi merhaba’yı değer olarak alıp sonuna bir metin ekledi. Çıktı:
1 |
Merhaba ben Messi. Ben futbolcu. |
Getter ve Setter
Klasik bir sınıftaki değer direkt erişildiğinde herhangi bir kontrol işlemi yapılamaz. Direkt veriler alınır. Sınıf içindeki değişkenleri kontrollü bir şekilde (örneğin sayı değeri sıfırdan büyük olsun) yönetmek için fonksiyonlar yazılır. Genelde bu fonksiyonlara get… ve set… fonksiyonları denir. get değer döndürmek ve set değeri ayarlamak için kullanılır. Fonksiyonlar yerine bir değişkenmiş gibi davranan yapıya property denir. Property değişken gibi erişilebilir ama bir fonksiyon gibi de kontroller yazmaya olanak sağlar. Örneğin,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class kisi2 { constructor(ad) { this.ad = ad; this.yas = 20; } merhaba() { return 'Merhaba ben ' + this.ad + '.'; } get bilgi(){ return this.ad + " " +this.yas; } set yasi(yas){ if(yas<1) this.yas = 1; else this.yas = yas; } } class futbolcu2 extends kisi2 { merhaba() { return super.merhaba() + ' Ben futbolcu.'; } } let messi2 = new futbolcu2('Messi'); console.log(messi2.bilgi); messi2.yasi = 21; console.log(messi2.bilgi); |
1 2 |
Messi 20 Messi 21 |
get_bilgi iki değişkeni alıp string bir sonuç döndürür. set değişkeni ise yas değerini kontrolden geçirerek alır. Eğer, yaş için birden küçük set edilirse this.yas 1 olarak ayarlanır. Nesne üzerinde get ve set sırasıyla messi2.bilgi ve messi2.yasi = 21 şeklinde ulaşılır. Dikkat ettiyseniz sanki bir değişkenmiş gibi ulaştınız, ancak fonksiyonda olduğu gibi kontrol üzerinden geçti.
Static Üyeler
Static üyeler new ile yaratmaya gerek kalmadan direkt sınıf üzerinden çağrılır. Örneğin,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class sayi{ constructor(s) { this.sayi = s; } static buyukmu(sayi1, sayi2) { return sayi1.sayi > sayi2.sayi ? true : false } } const s1 = new sayi(10) console.log(s1.sayi) const s2 = new sayi(20) console.log(s2.sayi) const s3 = new sayi(10) console.log(s3.sayi) console.log(sayi.buyukmu(s1, s2)) console.log(sayi.buyukmu(s2, s3)) console.log(sayi.buyukmu(s1, s3)) |
1 2 3 4 5 6 |
10 20 10 false true false |
3 sayı bir sınıf üzerinden nesne oluşturacak alınmış ve static buyukmu isminde iki nesneyi karşılaştıran bir fonksiyon yazılmıştır. Sayı değerine ulaşırken nesneİsmi.sayi şeklinde bir erişim söz konusu iken static fonksiyona ulaşmak için sınıfİsmi.fonksiyon şeklinde bir kullanım söz konusudur. Static bölümler nesne oluşurken yüklenir, sınıf içindeki diğer üyeler ise o nesneye özeldir. Eğer o sınıf için özel bir fonksiyon yazmıyorsanız, ancak fonksiyon sınıf ile alakalı ise static fonksiyon kullanmanızı öneririm. Static fonksiyonlar başlangıçta bir kez yaratıldığı için daha hızlı bir şekilde erişime destek verir. Nesne gibi bellekten yeni bir yer tahsisi beklemez.