OOP: Kapsülleme

OOP: Kapsülleme

Blogumda yazılım ile ilgili pek bir yazı olmadığından artık bazı konularda yazılar yazmaya karar verdim. Bu yüzden programlamanın en temel ve en önemli konularından biri olan Nesne Yönelimli Programlama’yı elimden geldiği kadar anlatmaya çalışacağım. Object Oriented Programming bir programlama yaklaşımıdır. Nesneye yönelik programlama, nesneye dayalı programlama, nesne tabanlı programlama, nesne esaslı programlama gibi bir çok çevirisi vardır. Ben de Türkçe de daha çok yaygın olan nesne yönelimli programlamayı kullanıyorum. Fakat genelde bahsederken OOP olarak kısaltacağım.

Yazılım gereksinimleri arttıkça prosedürel programlama bir çok sorunu beraberinde getiriyordu. Bu sorunlara kod karmaşıklığının artması, bakımın oldukça zor olması, ekip halinde çalışmayı zorlaştırması, maliyetlerin artması örnek olarak verilebilir. Bütün bu sorunların sonucu olarak da “Nesne Yönelimli Programlama” ortaya çıkmıştır. OOP ilk olarak 60’lı yıllarda Norveç’te geliştirilen “Simula” programlama dili ile ortaya çıkmıştır. Simula ise ALGOL tabanlı bir programlama dilidir. Günümüzde hemen hemen bütün modern diller OOP desteklemektedir. OOP’nin bu kadar popüler olmasının bir sebebi var. Merak edenler için “SOLID” anahtar kelimesini vereyim. Fakat bu yazı dizisinde OOP’nin en temel özelliklerini anlatacağım. OOP’yi anlatırken Java’da sınıflar ve nesneler konusunda bilgi sahibi olduğunuzu varsayacağım.

OOP denilince akla üç (bazı kaynaklara göre dört) özellik geliyor. Bunlar:

  • Encapsulation (Kapsülleme)
  • Inheritance (Kalıtım)
  • Polymorphism (Polimorfizm veya Çok biçimlilik)

Bazı kaynaklar Abstraction (Soyutlama)‘ı da dahil etmektedir. Daha önce ben de bu şekilde tanımlardım. Soyutlama ise çok daha geniş bir konu olduğundan üç özellik olarak tanımlamayı tercih ediyorum. Bu yazı dizisinde soyutlamaya da yer vereceğim.

Encapsulation (Kapsülleme)

Kapsülleme de aslında bir çok şekilde yapılabilir. Fakat basit olması amacı ile en kolay yönden tanımlayacağım.

Kapsüllemeyi kısaca tanımlarsak bir nesnenin iç yapısını (verilerini ve özelliklerini) dış dünyadan doğrudan erişime kapatılması anlamına gelir. Bu sayede nesneye ait veriler değer ataması yapılırken yanlış kullanımdan korunmuş olur. İç yapısının dışarıya açık olmaması aynı zamanda iç yapı ile ilgili değişikliklerin dış dünyanın etkilenmemesini de sağlamış olur. Bu açıdan çok önemlidir.

Java programlama dilinde nesne elemanlarının dışarıya kapatılması için private erişim belirteci kullanılır. Java’da dört erişim belirleyicisi (access modifier) vardır. Bunları kısaca tanımlarsak:

  • public: public kelimesi halka açık veya kamu anlamına gelmektedir. Bu erişim belirleyicisi ile tanımlanan herşey diğer bütün sınıflar tarafından erişilebilir.

  • private: özel veya gizli anlamına gelir. Bu erişim belirleyicisi ile tanımlanan herhangi bir eleman sadece ve sadece aynı sınıf içerisinden erişilebilir. Yani diğer sınıflar hiç bir şekilde erişemez.

  • package-private: Adı üstünde paket anlamına gelir. Bu erişim belirleyicisi ile işaretlenen herşey sadece ve sadece aynı paket içerisinde tanımlanan sınıflar tarafından erişilebilir. Farklı paketlerde bulunan sınıflar erişemez. Java’da değişkenleri, metodları vs. diğer erişim belirleyicisilerle tanımlamazsanız, package-private olarak tanımlamış olursunuz. Yani package veya package-private gibi kelimeler kullanılmaz.

  • protected: Korumalı anlamına gelir. Bu erişim belirleyicisi ile herhangi bir eleman türetilmiş olan ve aynı paket içerisinde olan sınıflar içerisinden erişilebilir. (Kalıtım konusunda anlatılacaktır.)

Bunlara kullanarak örnek bir sınıf tasarlayalım.

Payı (numerator) ve paydası (denominator) olan basit bir Rational (rasyonel) sınıfı tanımlayalım.

Bu sınıfın iki değişkeni var: numerator ve denominator. Bu iki değişken sınıfa ait olduğu için alan (field) olarak tanımlayabiliriz. Bu iki alanın erişim belirleyicisini private olarak belirledik. Bu sayede sınıf dışından erişimi kapatmış olduk. Örneğin başka bir sınıftan aşağıdaki gibi bir kullanım hatalı olacaktır.

Ayrıca dikkatlice incelerseniz Rational sınıfında IllegalDenominator sınıfı da tanımlanmış. Bu tür sınıflara inner-class diyoruz. Bu sınıfında bir erişim belirteci var. public olması sebebi ile bu sınıfa dışarıdan herkes erişebilir.

Rational sınıfına dikkat ederseniz getter ve setter metodlarımnız var (Örneğin: getNumerator(), setNumerator()). Bu metodların erişim belirleyicisi de public yani dışardan erişime açık. Bu sayede numerator ve denominator değişkenlerine bu metodlar aracılığı ile değer atanabilir. Aşağıdaki kullanım doğru olacaktır.

setNumerator ve setDenominator sayesinde numerator ve denominator değişkenlerine değer atanmış oldu. Burada gördüğünüz set ile başlayan metodlara setter adı verilir. Aynı şekilde bu alanların değerlerine erişmek için getNumerator ve getDenominator metodlarını kullanabiliriz. Bu şekilde tanımlanan metodlara da getter adı verilir.

setDenominator metodunu detaylı inceleyelim. 15. satırda bir koşul olduğunu görüyorsunuz. Eğer denominator’e yani paydaya 0 değeri atanmaya çalışıldığında, bu metod Exception fırlatarak paydanın 0 olmasını engellemiş oluyor. Bu sayede yanlış kullanımı engellemiş olduk. Bu sayede veri bütünlüğü ve kontrolü sağlanmış oldu. Genelde bütün alanlar geçerli bir sebep olmadıkça private olarak tanımlanır. Yani dışarıya kapatılmalıdır. Her alan için getter ve setter metodları tanımlamak zorundayız diye de düşünmeyin. Böyle bir zorunluluk yok. getter ve setter metodlar olmadan farklı metodlar aracılığı ile de erişimi kontrol altına alabilirsiniz. Örneğin sınıfımıza 3 tane constructor metod ekleyelim.

Bu tasarımımız da farklı bir örnek oldu. Dikkat ederseniz bu tasarımımızda setter metodları kaldırdık. Bu sınıfı kullanan istemci artık sadece nesne üretirkendeğerleri verebilecek nesne üretildikten sonra değerini değiştiremeyecektir. nominator ve denominator değişkenleriniprivate olarak tanımladığımız için istemcinin doğrudan ne de dolaylı olarak değerini değiştiremez. Bu tarz sınıflara immutable sınıf adı verilir.

Bu yazıda kısaca encapsulation yani kapsüllemeyi anlattım. Bir sonraki yazıda görüşmek üzere…

oop encapsulation java public private package-private protected