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 Esaslı 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 gibi bir çok çevirisi vardır. Ben de Türkçe olarak “Nesne Esaslı Programlama” olarak adlandırıyorum. OOP’den önce daha çok prosedürel(yordamsal) programlama yaklaşımı kullanılıyordu. 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 Esaslı Programlama ortaya çıkmıştır. Nesne esaslı programlama’nın İngilizce kısaltması olan OOP’yi kullanacağım. OOP’yi anlatırken Java’da sınıflar ve nesneler konusunda bilgi sahibi olduğunuzu varsayacağım.

Genelde yazılım veya bilgisayar mühendisliği öğrencilerinin algoritmadan sonra öğrenmesi gereken en önemli konulardan biridir. Günümüzde birçok programlama dili OOP’yi destekler. Nesne esaslı programlamanın temel olarak 4 özelliği vardır. Bunlar:

  • Kapsülleme (encapsulation)
  • Soyutlama (abstraction)
  • Kalıtım (inheritance)
  • Çok biçimlilik (polymorphism)

 Kapsülleme — Encapsulation

Kapsüllemeyi kısaca tanımlarsak bir nesnenin verilerini ve özelliklerini diğer nesnelerin 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. Java programlama dilinde dört erişim belirleyicisi (access modifier) vardır. Bunlar:

  1. public: public kelimesi halka açık veya kamu anlamına gelmektedir. Bu erişim belirleyicisi ile tanımlanan değişkenler ve metodlar bütün nesneler tarafından erişilebilir.
  2. private: private özel veya gizli anlamına gelir. Bu erişim belirleyicisi ile tanımlanan değişkenler ve metodlar sadece sınıf içerisinden erişilebilir.
  3. protected:  protected korumalı anlamına gelir. Bu erişim belirleyicisi ile tanımlanan değişkenler türetilmiş olan ve aynı paket içerisinde olan sınıflar içerisinden erişilebilir. (Kalıtım konusunda anlatılacaktır.)
  4. package — default: default varsayılan anlamına gelir.  Herhangi bir erişim belirleyicisi (public,protected ve private) ile tanımlanmadığı zaman “package (paket)” olarak tanımlanmış olur. Sadece aynı paket içerisinde tanımlanan sınıflar tarafından erişilebilir.

Erişim belirleyicileri kullanarak o veriye doğrudan erişimi sınırlandırabiliriz. Basit bir örnek verelim.

Payı (numerator) ve paydası (denominator) özelliklerine sahip olan basit bir Rational (rasyonel) sınıfı tanımladık. 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.

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 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 ( istisna) fırlatarak paydanın 0 olmasını engellemiş oluyor. Bu sayede yanlış kullanımı engellemiş olduk. Gördüğünüz gibi kapsülleme uygulamış olduk. Java’da genelde alanlar private olarak tanımlanı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 ( yapılandırıcı) metod ekleyelim.

Sınıfımızın son hali yukardaki gibidir.

Property (Özellik)

Kapsülleme ile property’ler bazen karıştırılmaktadır. O yüzden bu konuya da değinmek istiyorum. Bazı programlama dillerinde ( C# gibi ) property özelliği söz dizimi(syntax) olarak tanımlanmıştır. Bazı programlama dillerinde ise (Java gibi) kural olarak tanımlanır. Property’lere örnek olarak yukarda tanımladığımız getter ve setter metodları verebiliriz. Property’ler getter ve setter metodlardan oluşur. Kapsülleme ise bir değişkenin dışardan erişime kapatılması demektir. getter ve setter metodları oluşturmasaydık property oluşturmamış fakat sınıf değişkenlerini dışarıya kapattığımız için yine kapsülleme yapmış olacaktık.

Not: C#’ta property örneği için aşağıdaki sınıfa bakabilirsiniz.

C# için property’ler yukardaki gibi tanımlanır. Örneğin sınıf dışından “rational.Field= 3″ şekilde kullanabiliriz. Burada dikkat edeceğiniz önemli bir standart vardır. Property tanımlanırken ilgili değişken ile aynı adı almalı ve baş harfi büyük olmalıdır.

Java için ise aynı sınıfı tanımlarsak:

Java’nın söz diziminde  property’ler olmadığından getter ve setter metod kullanılır. getter tanımlarken değişken adının önüne ek olarak “get” eki getirilmeli ve değişkenin baş harfi büyük olmalıdır (getField). setter için ise aynı şey söz konusudur.

Not: Bu kurallar programlama dili için bir zorunluluk değildir. Fakat programcılar arasında kullanılan birer standarttır. Yazdığınız kodların okunması ve framework’lerle kullanımda sorun yaşanmaması için bu kurallara uyulmasına özen gösterilmelidir.

Bu yazımda OOP’nin temel özelliklerinden biri olan kapsüllemeden bahsettim. Diğer özellikleri başka yazılarımda anlatacağım.

İyi çalışmalar