fka blog journal of programming studies

Object Oriented Javascript'e Giriş: Prototype Tabanlı Kalıtım (Prototype-Based Inheritance)

Merhaba,

Nesnel Javascript’e Giriş dizisinin bundan bir önceki başlığında prototiplere temel olarak değinmiş ve örnek bir sınıf yazmıştık. Prototiplerin bir sınıfın nesneye gönderdiği değerleri olduğunu görmüştük.

İnternet üzerinde bulduğum bir şema üzerinden gitmek istiyorum.

Prototype

Aslında bütün olay bu. Şimdi bu şemanın bir de kodunu yazalım ki anlatması daha kolay olsun.

Burada A fonksiyonu ile B fonksiyonu arasında organik bir bağ yok. Fakat şemada gördüğümüz gibi X’nin __proto__ su B’nin prototype‘ına eşit. Demek ki bunları kalıtmak için bu şekilde bir yapıya eriştirmemiz gerekiyor.

Şimdi mantık çerçevesinde düşünelim, bizim bir Animal nesnemiz olsun. Bu Animal nesnesinin prototipinde nesne bazlı değişkenler olsun, her nesneye göre değişebilen değerler. Her nesne yarattığımızda bu değerler nesnenin kendisine has değerler olsun. Fakat biz yeni bir sınıf oluşturmak istiyoruz ve bu da Animal sınıfından türemiş olmalı. Bird adlı bir sınıfımız olmalı ve bu da Animal sınıfının prototipine sahip olmalı ki, yeni türeyen nesneler Bird’in aynı zamanda da Animal’ın prototipine sahip olsun. Fakat constructor Animal’ın değil, Bird’in kendisi olmalı.

Son cümleyi tekrar yazıyorum: **Bird adlı bir sınıfımız olmalı ve bu da Animal sınıfının prototipine sahip olmalı ki, yeni türeyen nesneler Bird’in aynı zamanda da Animal’ın prototipine sahip olsun. İşte burda tüm mantığı anlattık zaten. İki prototipi birleştirmemiz gerekiyor. Peki bunu nasıl yapabiliriz?

Yukarıdaki şemaya göre baktığımızda, B’nin A’nın prototipini kalıtıyor olması gerektiğini görürüz. Yani B.prototype = A.prototype dersek olabilir gibi görünüyor… Hemen bakalım:

Evet gördüğümüz gibi oldu. Fakat bir sorun var burada. Eğer biz B.prototype’ı değil de A.prototype’ı değştirmek istersek, ondan kalıtılan A da etkilenecek. Hemen örnek verelim:

Demek ki, B.prototype = A.prototype yaptığımızda klonlama değil, referans gösterme işlemi yapmış oluyormuşuz. Fakat bizim işimize yarayan, klonlamak. JavaScript’te klonlama işini ise Object.create methodu yapar.

Sorun var. Her iki sınıf da kendi constructor‘unu en tepedeki constructor sanıyor. O halde bunu düzenlememiz lazım. Fakat bu sorun neden kaynaklandı buna değinelim. B.prototype’a A.prototype’dan bir kopya atadığımızda, aslında constructor’u da atıyoruz, çünkü A.prototype.constructor, fonksiyonun kendisini veriyor. O halde kopyalamadan sonra, bozulan constructoru geri almalıyız.

Evet kalıtımlı bir sınıf oluşturduk. Şimdi tek bir sorunumuz kaldı, B’nin prototipi, kalıtıldığı sınıfa nasıl ulaşacak? Yani parent’a.

__proto__ nesnesi, nesnenin asıl prototipini kendisine söyler. B sınıfının asıl prototipi A olduğu için __proto__ üzerinden bir üst sınıfa erişim sağlayabiliriz.

Demek ki, this.__proto__ kendi kendisinin prototipini verirken, this.__proto__.__proto__ prototipinin asıl prototipini yani üst sınıfı verecek. Yani diğer dillerdeki parent, super mantığı, JavaScript’te this.__proto__.__proto__ :) Biraz uzun fakat kısaltmak imkansız değil.

Object.prototype.super = function() {
  return this.__proto__.__proto__;
}

diyerek this.super().constructor şeklinde bir erişim sağlayabilirsiniz.

Burada aynı zamanda, Object nesnesine de bir method eklemiş ve bir örnek yaratmış olduk :)

Bir dahaki konuda sınıf oluşturmak için kullandığımız bu yöntemlerin nasıl daha kısaltabileceğimiz konusuna değineceğiz :) Ayrıca __defineGetter__ ve __defineSetter__ özelliklerine de değineceğiz. Son değindiğimiz super() konusunu biraz daha kısaltabiliriz :)

Teşekkürler.