BG MVC Model View Controller eğitim serisi yayında...

Ana sayfa > Programlama > C++ Programlama > Nesneye yönelik programlama

Nesneye yönelik programlama

Bilgisayar kullanımı ile birlikte programlama her geçen gün farklı boyutlarda gelişmeye devam etmektedir. Başlangıçta, yazılım geliştirme açısından zaman ve çalışma gerektiren direk makine kodlarının kullanımı ile hayata geçirilen bilgisayar programları için, ihtiyaçların artması ve daha kısa zamanda sonuca ulaşma ihtiyacı ile birlikte daha farklı yöntemlerle geliştirilmeye başlanmıştır.

Önceleri Assembly dilinin daha sonra da FORTRAN gibi yüksek seviyeli programlama dillerinin icadı ile programların daha kolay bir şekilde geliştirilmesine olanak sağlanmıştır.

Programların istenilen özellikleri karşılamasında yaşanan sıkıntılarla birlikte yapısal programlama adı verilen bir kavram geliştirilmiştir. C ve Pascal gibi programlama dilleri ile gelen bu özellikle, fonksiyon ve kod bloğu gibi toplu kod tanımlamaları ve bu kod bloklarının aynı isimlerle defalarca çağrılabilmesi daha karışık ve büyük çaplı kodların daha okunur ve açık bir şekilde düzenlenebilmesi sağlanmıştır.

Programlama yaparken daha büyük kolaylıklara ihtiyaç duyulunca, belirli verilerin bu verilerle ilgili kodlarla ilişkilendirilmesi temel prensibine bağlı olan Nesneye Yönelik Programlama (Object Oriented Programming) kavramı geliştirilmiştir. Bu kavram ile birlikte, verilere işlem yapacak kodların metod adı verilen fonksiyonlar içinde yazılması ve verilerle birlikte tek bir yapı içinde tanımlanması ve tüm işlem yetkilerinin bu yapı içinde belirlenmesi esas alınmıştır.

Nesneye yönelik programlama, Kapsülleme (Encapsulation), Kalıtım (Inheritance) ve Çok biçimlilik (Polymorphism) adı verilen dört temel kavramı esas alarak çalışır. Bu esasları gerçekleştirmek için de Sınıf (Class) ve Nesne (Object) kavramlarını kullanır.

Soyutlama (Abstraction)

Soyutlama, kullanıcıya yalnızca ilgili ayrıntıların gösterilmesi ve ilgisiz ayrıntıların gizlenmesi olarak ifade edilebilir. C++'da kullanılan temel soyutlama sistemleri sınıflar, sınıflar yoluyla yapılan kalıtım ve şablonlardır.

Soyutlama, genellikle veri soyutlama amacıyla kullanılır. Veri soyutlama kullanımı için, içinde en az bir adet saf sanal fonksiyon bulunan soyut (abstract) bir sınıf oluşturulur. Bir sınıf içinde en az bir adet saf sanal fonksiyon tanımlanırsa, bu sınıf soyut (abstract) sınıf haline gelir. Bu soyut sınıf kendisinden türetilen alt sınıfların ortak değişkenlerini ve fonksiyonlarını içerir. Soyut bir sınıftan türetilen tüm sınıflarda sanal fonksiyon bildirimi yeniden yapılmalıdır. Eğer yapılmazsa, türetilen sınıflarda soyut sınıf olarak kabul edilir. Soyut sınıflar saf sanal fonksiyon dışında normal fonksiyonlar ve değişkenler içerebilir.

Soyut sınıfları kullanılarak geliştirilen yazılımlarda değişiklik yapmak gerektiğinde, soyut sınıflarda yer alan ve türetilen sınıflar tarafından kullanılan private erişim özelliğine değişkenlerin değiştirilmesi yeterli olmaktadır. Soyut sınıflarda bildirimi yapılan private değişkenler veri güvenliğini artırır ve program kodlarının daha pratik yazılmasını sağlar.

Kapsülleme (Encapsulation)

Kapsülleme, programda bir sınıf içinde tanımlanan verileri ve yine aynı sınıf içinde tanımlanan ve bu verilere erişim sağlayarak kullanan metod veya fonksiyon adı verilen sistemi ifade eder. Bu sistemle, sınıf içinde ye alan veriler ve bu verilere erişim sağlayan kodlar bir bütünlük içinde korunarak, dışarıdan erişimi kısıtlanır. Böylece, program kendi içinde bir kod ve veri güvenliği sağlar. Bu sistemde, kod ve veri tek bir isim altında tanımlanarak, oluşturulan bir sınıf içindeki veri ve kodlar (metodlar) korunur.

Kapsülleme verileri ve bu verileri kullanan ya da değiştiren program kodlarını birbirine bağlayarak dışarıdan yapılabilecek müdahalelere karşı koruyan bir sistemdir. Nesneye yönelik programlamada, bir sınıf tanımlaması altında kod ve veri bu şekilde koruma altına alındığında bir nesne oluşturulmuş olur. Nesne kapsamındaki veri ve verilere işlem yapan kodlar, sadece içinde tanımlı olduğu nesne tarafından (private) veya dışarıdan erişilecek şekilde (public) tanımlanabilir. Nesne içinde private olarak tanımlanmış özel kod ve verilere sadece nesne içinde yer alan diğer kodlar tarafından erişilebilir. Nesne dışında yer alan kodlar nesneye ve özel verilere erişemezler.

Nesne içinde public olarak tanımlanan kod ve veriler tüm erişimlere açık olduğundan, programın nesne dışında kalan kodları bu kod ve verilere erişim sağlar. Nesne içinde programdaki tüm kodların erişimine açık veri ve kodlar açık olarak tanımlanır. Tüm erişimlere açık olan nesne elemanları, nesneye özel elemanlara erişim için kullanılır. Bu durumda, nesne dışındaki kodlar nesne içindeki tüm erişimlere açık kodlar yoluyla nesne içindeki nesneye özel veri ve kodlara da erişebilirler.

Kalıtım (Inheritance)

Kalıtım nesneye yönelik programlamanın en önemli özelliklerinden biridir. Kalıtım bir nesneden türetilen bir nesnenin türetildiği nesnenin tüm özelliklerine sahip olmasıdır.

Kalıtım, nesneye yönelik programlamada mevcut bir sınıf içinde bulunan veri ve metotların bu sınıftan türetilen alt sınıflar içinde kullanılması olarak tanımlanabilir.

Kendisinden sınıf türetilen sınıf ana, ebeveyn veya süper sınıf olarak, türetilen sınıflar ise çocuk, alt veya uzantı sınıf olarak isimlendirilir.

Bir ana sınıftan yeni bir çocuk sınıf türetildiğinde, ana sınıfta yer alan tüm veri ve metotlar çocuk sınıf tarafından kullanılabileceği gibi, çocuk sınıf içinde de yeni veri ve metotlar tanımlanabilir. Eğer ihtiyaç duyulursa, ana sınıftan devralınan metotlar geçersiz hale getirilir (overriding) ve aynı isim altında farklı kodlar yazılır.

Ana sınıftan bir çocuk sınıf türeterek, ana sınıfta yer alan veri ve metotların devralınması, devralınan metotlar için yeniden kod yazmaya gerek duymadan, ana sınıf içinde yer alan veri ve metotları kullanmaya olanak sağlar.

Çok biçimlilik (Polymorphism)

Çok biçimlilik sözlük anlamı olarak birden fazla şekilde varlık gösterebilen nesne ya da kavramları ifade etmektedir. Nesneye yönelik programlamada ise, çok biçimlilik fonksiyon ve işlemcilerin birden fazla görev için kullanılmaları ile kalıtım ve sanal fonksiyonların kullanılmasını içerir.

C++'da, çok biçimlilik kavramını aşağıda gösterilen dört farklı yöntemle uygulayabiliriz:

  • Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi
  • İşlemcilere çoklu görev tanımlama (Overloading) işlemi
  • Sınıf fonksiyonlarını doğrudan yeniden tanımlama (Overriding)
  • Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama (Overriding)

Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi

C++'da, fonksiyonlar için çoklu görev tanımlama (overloading) işlemi yapılırken çok biçimlilik özelliği kullanılır. Birden fazla fonksiyon, farklı veri türündeki ve/veya farklı sayıda parametrelerle bildirimleri yapıldığında, aynı ismi kullanır ve program içinden farklı parametreler ve aynı isim ile çağrılırlarsa, fonksiyon çoklu görev tanımlama işlemi gerçekleştirilmiş olur. Böylece, program içinde tek bir isim kullanarak birden fazla fonksiyona erişim sağlanabilir. Burada kullanılan çoklu görev tanımlama ifadesi birden fazla fonksiyonun aynı isim ile çağrılarak kullanılmasını gösterir. Böyle bir fonksiyon çağırıldığında, çağrı fonksiyon çağrısında kullanılan parametre sayısı ve tiplerine uygun olarak ilgili fonksiyona yönlendirilir.

İşlemcilere çoklu görev tanımlama (Overloading) işlemi

C++'da, işlemci çoklu görev tanımlama işlemi yapılırken de çok biçimlilik özelliği kullanılır. Bir işlemci için çoklu görev tanımlaması yapıldığında, sahip olduğu özelliklerin yanı sıra, bir sınıfa bağlı olarak ek işlem yapma özelliği kazanır. Bir işlemci için çoklu görev tanımlaması yapıldığında yani birden fazla işlem yapma kapasitesi kazandırıldığında, işlemcinin orjinal fonksiyonu ortadan kalkmaz. İşlemciler için çoklu görev tanımlaması yapmak amacıyla işlemci fonksiyonları oluşturulur. Bir işlemci fonksiyonu, çoklu görev tanımlaması uygulanan işlemcinin bağlı olduğu sınıfa göre gerçekleştireceği işlemleri tanımlar. İşlemci fonksiyonu operator anahtar kelimesi kullanılarak oluşturulur. İşlemci fonksiyonları, bir sınıfın üyesi olabilir veya olmayabilir. Üye olmayan işlemci fonksiyonları, sınıf için friend fonksiyon olarak tanımlanır. İşlemci fonksiyonlarının yapısı sınıf üyesi olma ve olmama durumuna göre farklılık gösterir.

Bir ana sınıftan bir sınıf türetildiğinde, ana sınıfta yer alan tüm veri ve metotlar türetilen sınıf tarafından kullanılabileceği gibi, türetilen sınıf içinde de yeni veri ve metotlar tanımlanabilir. Eğer ihtiyaç duyulursa, ana sınıftan devralınan metotlar geçersiz hale getirilir (overriding) ve aynı isim altında farklı kodlar yazılır. Bu durumda, aynı fonksiyon hem ana sınıfta hem de türetilmiş sınıfta tanımlanmış olur. Bu fonksiyon türetilmiş sınıf nesnesi ile çağrıldığında, türetilmiş sınıfın fonksiyonu çağrılır. Bu özelliğe, Fonksiyonu Yeniden Tanımlama adı verilir. Türetilmiş sınıftaki fonksiyon, ana sınıftaki fonksiyonun yerini alır.

Fonksiyonu yeniden tanımlama işleminin yapılabilmesi için, bir ana sınıftan bir sınıf türetilmesine, kalıtım özelliğinin kullanılmasına, ihtiyaç vardır.

Fonksiyonları yeniden tanımlama işlemi, bir ana sınıf ve ana sınıftan türetilmiş olan bir veya daha fazla türetilmiş sınıf içinde yapılır. Bu işlem iki farklı yöntemle uygulanabilir:

Sınıf fonksiyonlarını doğrudan yeniden tanımlama

Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama

Sınıf fonksiyonlarını doğrudan yeniden tanımlama (Overriding)

Sınıf üye fonksiyonlarını yeniden tanımlama işlemi yaparken, ana sınıf içinde tanımlanan bir fonksiyon ile aynı isme sahip bir fonksiyon ana sınıftan türetilmiş bir sınıf içinde tanımlanır ve kod içeriği yeniden yazılır. Bu durumda, ana sınıf ve bu sınıf içinde aynı isme sahip iki fonksiyon oluşturulur. Bu fonksiyonlara ana sınıf ve türetilmiş sınıftan oluşturulan işaretçi ve nesneler yoluyla yapılan erişimler aşağıda gösterilen esaslara göre yapılmaktadır:

Doğrudan yeniden tanımlama yönteminde, ana sınıf işaretçisine türetilen sınıf nesnesinin adresi atandığında, ana sınıf işaretçisi ana sınıf içindeki fonksiyonlara erişim sağlar.

Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama (Overriding)

Sanal fonksiyonlar, çalışma zamanı çok biçimlilik (Runtime Polymorphism) özelliği sağlar. Sanal bir fonksiyon oluşturmak için, ana sınıf içindeki fonksiyon bildiriminden önce virtual anahtar kelimesi kullanılır. Sanal fonksiyon içeren bir sınıftan yeni bir sınıf türetildiğinde, türetilen her sınıf içinde sanal fonksiyon, virtual anahtar kelimesi kullanılmadan, yeniden tanımlanır ve fonksiyon içeriği yeniden düzenlenir. Bu özellikle, virtual anahtar kelimesi derleyiciye fonksiyon bağlama işlemini derleme zamanında değil çalışma zamanında yapmasını bildirir. Sanal fonksiyon ile, aynı isme sahip bir fonksiyon her sınıf için ayrı bir işlem yapacak şekilde tanımlanabilmektedir. Bu durum nesneye yönelik programlamada çok biçimlilik (Polymorphism) özelliğinin bir sonucudur. İşaretçi kullanarak erişim sağlamak sanal fonksiyonları sınıf içindeki diğer fonksiyonlardan farklı hale getirir. Ana sınıf türünden oluşturulan bir işaretçi ana sınıf ve ana sınıftan türetilen tüm sınıflar içindeki sanal fonksiyonlara erişim sağlayabilir.

Sanal yöntemle yeniden tanımlama yönteminde, ana sınıf işaretçisine türetilen sınıf nesnesinin adresi atandığında, ana sınıf işaretçisi türetilen sınıf içindeki fonksiyonlara erişim sağlar.

Sınıf

Nesneye yönelik programlama (NYP) çalışma sistemi 2 temel kavram üzerinde şekillenir:

1. Değişkenler (veriler): NYP ile geliştirilen uygulamalarda ihtiyaç duyulan farklı türden değişkenler sınıf içinde tanımlanır.

2. Değişkenlere işlem yapan fonksiyonlar (metodlar): NYP ile geliştirilen uygulamalarda sınıf içinde tanımlanan değişkenlere işlem yapmak üzere fonksiyonlar içinde kodlar tanımlanır.

NYP ile geliştirilen uygulamalarda program içinde, veriler ile verilere işlem yapacak olan fonksiyonlar (metodlar) sınıf (class) adı verilen yapıların içinde tanımlanır. Sınıf tanımlandıktan sonra bu sınıf türünden bir değişken (nesne) oluşturularak, bu nesne yoluyla sınıf içinde yer alan tüm değişken ve fonksiyonlara erişim sağlanır.

Nesne

Bir nesne oluşturmadan önce, class anahtar kelimesini kullanarak nesnenin tüm özellik (değişkenler) ve davranışlarını (fonksiyonlar) gösteren genel yapısını tanımlamamız gerekir.

Sınıflar class anahtar kelimesi ile oluşturulur. Bir sınıf oluşturulduğunda, sınıf içindeki değişkenlere yine sınıf içindeki fonksiyonların işlem yapmasını sağlayan yeni bir veri türü tanımlanmış olur.

Sınıf adı verilen bu yeni veri türü oluşturulduktan sonra, bu sınıfa ait nesne bildirimi yapılır. Bu işlem, int bir veri türünden değişken tanımlamaya benzer.