C# Object Oriented Programming (Nesne Yönelimli Programlama)

İlgili resim

Merhaba arkadaşlar,

Bu yazımda modern programlama dillerinin olmazsa olmazı olan Nesne Yönelim Programlama tekniği bahsedip C# programlama dili ile nesne yönelimli programlama tekniğini uygulayabilmek için bilmemiz gereken en temel kavramları ele alacağız. Nesne yönelimli programlamaya geçmeden önce ilginizi çekerse bir önceki blog yazım olan Regular Expression ( Düzenli İfadeler ) buradan erişebilirsiniz.

Nesne yönelimli programlama tekniği yazılım geliştirme aşamasını sistematik hale getiren ve oldukça kısaltan bir tekniktir. C# dili de zaten %100 Nesne Yönelimli Programlamayı destekler.

Bu yazıda bahsedilecek konular

  • Nesne Yönelimli Programlama Neden Önemli
  • Nesne Yönelimli Programlama
  • Diğer Programlama Teknikleri
  • Nesne Kavramı
  • Kalıtım (Inheritance)
  • Protected Erişim Belirleyicisi
  • Yapıcı Metotların Kalıtımdaki Rolü
  • İsim Saklama (Name Hiding)
  • Temel ve Türeyen Sınıf Nesneleri
  • Sanal Metotlar
  • Abstract (Özet) Sınıflar
  • sealed Anahtar Sözcüğü
  • Interface (Arayüzler)
  • Arayüz Referansları
  • Açık (Explicit) Arayüz Uygulama
  • Partial (Kısmi) Tipler

Nesne Yönelimli Programlama Neden Önemli?

1960 yıllarda genellikle ihtiyaca göre küçük programlar geliştiriliyordu. Bu yüzden kullanılan diller Assembly, Fortan, Cobol gibi basit programlama dilleriydi. Ancak gün geçtikçe teknoloji hızla gelişti ve o dönemde yazılan programlar artık ihtiyaca karşılık veremiyordu. Tam bu noktada günümüzde de halen yoğun bir şekilde kullanılan C programlama dili ortaya çıktı. Bu dil sayesinde fonksiyon mantığı kullanılarak hem sistemli programlar yapılıyordu hem de fonksiyonlar değişik programlarda tekrar kullanılabiliyordu. 80’li yılların ortalarında ilişkisel veri modeline dayalı nesne yönelimli programlama tekniğine adım atıldı. Nesne yönelimli programlama tekniğine uygun dil olarak SmalTalk ortaya çıktı. Ancak en büyük gelişme C programlama dilinin devamı olarak görülen C++ programlama dili ile oldu. Çünkü C++ hem C‘de olduğu gibi yapısal programlamaya imkan tanıyor hem de çağın yeni tekniği olan nesne yönelimli programlama tekniğini destekliyordu. Bu sayede nesne yönelimli programlama dünya üzerinde kabul gören en yaygın programlama tekniği olmaya başladı. C++ programlama dilinin başarısı sayesinde diğer dillerin ortaya çıkmasına yol açtı. Bunların en başında JAVA programlama dili gelmektedir. JAVA C++ dilinden faklı olarak İnternet uygulamalarına ağırlık vermiş ve daha yaygın bir kullanım hedeflemişti. Bu gelişmeden sonra Microsoft ekibi yeni bir dil olarak C# programlama dilini geliştirdi. C# dili C++ ve JAVA dilleri gibi nesne yönelimli programlama tekniğini destekliyordu. Bu üç dili karşılaştıracak olursak C#‘ta nesne yönelimli programlama desteğinin yüzde yüz olduğu söylenebilir.

Nesne Yönelimli Programlama

Nesne yönelim tekniği, gerçek hayatta programları simule edecek yöntemler topluluğudur. Her nesnenin kendine has özellikleri vardır. Nesneler tamamen birbirinden soyutlanarak farklılaşabilirler. Her nesnenin de birbirine mesaj göndermesi son derece doğaldır. Nesne yönelimli programlama tekniğinde sistem parçalara bölünür ve bu parçalar arasında ilişkiler kurulur. Her bir parça hiyerarşik yapıda olabileceği gibi parçalar birbirinden tamamen bağımsız da olabilir. Burada önemli olan her parçayı etkili bir şekilde tasarlamak. Bu parçalardan kasıt aslında Sınıf nesnelerinden başka bir şey değildir.

  1. Nesne yönelimli programlama tekniğinin en küçük yapı taşı nesnelerdir (objects). Nesneler yapılarında veriler bulundururlar. Bu veriler arasında belirli ilişkiler sağlayan fonksiyonlar vardır. Nesnelerin bu şekilde veriler barındırması ve fonksiyonlar içermesine sarmalama (encapsulation) denilmektedir.
  2. Nesne içindeki veriler ve fonksiyonlar nesnenin dışarıya nasıl bir hizmet verdiğini belirler. Nesnenin servislerinden faydalanabilmek için nesnenin dış dünyaya sunduğu arayüzü bilmemiz yeterlidir. Nesne yönelimli teknik jargonunda buna Bilgi Saklama (Information Hiding) denilmektedir.
  3. Nesneler birbirinden bağımsız olmasına rağmen birbirleri ile haberleşebilir. Hangi nesnenin hangi nesneye mesaj göndereceği derleme aşamasında belli olmayabilir. Bu duruma nesne yönelimli programlama tekniğinin bir diğer önemli özelliği olan geç bağlama (late binding) devreye girer.
  4. Derleme zamanında hangi nesnenin hangi fonksiyonu kullanacağı belli olmayabilir. Aynı zamanda nesneler arasında mesajlaşmanın hangi nesneler arasında olacağı da derleme zamanında belirli olmayabilir. Bu durumda nesne yönelimli programlama tekniğinin çalışma zamanında bağlama mekanizmasından faydalanmaktadır. (late binding)
  5. Tüm nesneler birer sınıf örneğidir. Sınıflar nesnenin özelliğini belirler. Nesneler çalışma zamanında oluşacağı gibi derleme zamanında da oluşurlar.
  6. Kalıtım yolu ile sınıflar birbirinden türeyebilir. Bir sınıf diğer sınıftan türediği zaman türediği sınıfın özelliklerini kazanır. Bunun yanında kendine has özellikleri de bulunabilir. Nesne yönelimli programlamanın en önemli özelliği ise kalıtım yolu ile sınıfların birbirinden türemesidir.
  7. Nesne yönelimli programlama tekniğinde nesneler çok biçimli olabilirler. Çok biçimlilik (polymorphism) kavramı da türetme ile yakından ilgilidir. Anlamı ise bir nesnenin farklı bir şekillerde davranabilmesidir.

Diğer Programlama Teknikleri

Programla teknikleri geçmişten günümüze çeşitli süreçlerden geçmiştir.

  • Nesne Tabanlı Programlama (Object-based Programming): Bu teknikte nesneler sıklıkla kullanılır. Veriler nesneler içinde toplanmıştır. Fakat bütün nesneler birbirinden bağımsızdır. Ayrıca sınıf, kalıtım ve geç bağlama gibi kavramlar bu teknikte kullanılmazlar
  • Sınıf Tabanlı Programlama (Class-based Programming): Nesne tabanlı programlamaya ek olarak bu teknikte sınıf kavramı ve sınıf örnekleri kavramı yer alır.
  • Nesne yönelimli programlama (Object Oritented Programming): Sınıf tabanlı programlamanın bütün özellikleri yanında basit kalıtım kavramını da içerir.
  • İleri Nesne Yönelimli Programlama (Advanced OOP): Nesne yönelimli programlama tekniklerinin bütün kavramları yanı sıra çoklu türetme ve nesneler arasında ilişki belirleme gibi ileri teknikleri ile birlikte kullanıldığı programlama biçimidir.

Nesne Kavramı

Nesneler gerçek hayatta görebildiğimiz ya da varlığını bildiğimiz eşyalardır. Şu an dokunduğunuz bilgisayar, oturduğunuz sandalye, içinde bulunduğunuz ev vs.. gibi kavramlar birer nesnedir.

  • Nesne yönelimli programlama tekniğinde sınıflar nesnelerin biçimlerini belirlerler.
  • Oluşturduğumuz nesneler sınıf türünden nesneler olarak da adlandırılabilir.
  • Her bir nesne kendi içinde tutarlı bir yapıya sahiptir. Yani veriler arasında sıkı bir bağ vardır.

C# nesne yönelimli programlama yapısını sınıflar sağlar.

Kalıtım (Inheritance)

Kalıtım nesne yönelimli programlamanın en önemli tekniğidir. Kalıtım yolu ile nesneler birbirinden türetilir. Türeyen sınıflar türetilen sınıfların özelliklerini kazandıkları gibi kendileri de yeni özellikler tanımlayabilir. Türetme yoluyla bir nesne kendi özelliklerini diğer nesneye aktarır. İstenirse türeyen nesne kendine has özelliklerde içerebilir. Türetme ile sınıflar arasında hiyerarşik bir yapı sağlanmış olur.

Temel (base) sınıf burada Mammal ve türemiş sınıf ise Dog sınıfıdır. Bu sayede Dog sınıfı temel sınıf olan Mammal sınıfının özelliklerini kazanmış oldu. Ayrıca kendine has özellik ya da fonksiyon barındırabilir.

Protected Erişim Belirleyicisi

Kalıtım yolu ile public ya da protected elemanlar aktarılırlar. Temel sınıfta bulunan private üye elemanları türeyen sınıf içinden ulaşılamaz. protected eleman içeren bir sınıf türetildiğinde bu elemanlar türemiş sınıflarda rahatlıkla kullanılabilirler. protected elemanlar diğer sınıflar için private olarak kalmaya devam ederler.

private özellikte bir elemanı temel sınıfa ekledikten sonra türemiş sınıflarda kullanmaya çalıştığımızda aşağıdaki hatayı alırız.

Yukarıdaki örnekte Mammal sınıfına private özelliği eklendikten sonra Dog sınıfı içinden erişilemediği görülüyor ancak protected erişim belirleyicileri olan üye elamanlara Dog üzerinden erişebiliyoruz.

Yapıcı Metotların Kalıtımdaki Rolü

Nesne yönelimli programla da tanımlanan yapıcı metotlar en temel sınıftan türemiş sınıflara doğru çağrılacaktır. Yapıcı metotlar ile ilgili en önemli konu ise her yapıcı metodun kendi tanımlandığı sınıfın üye elamanları ile ilgili iş yapması gerekliliğidir. Bu zorunlu değildir ama nesne yönelimli programlama tekniğini daha etkili kullanmak için gereklidir.

Şimdi temel sınıftan türemiş sınıfa doğru yapıcı metotları tanımladıktan sonra bir örnek yapalım.

Yukarıdaki örnekte ilk başta temel sınıf olan Mammal sınıfının yapıcı metodu çağrıldıktan sonra Dog sınıfının yapıcı metodu çağrılır.

Yapıcı metot ile atama ilgili nesnenin üye elamanlarına değer atayabiliriz. Böylece her elemanın ilk değer ataması ilgili yapıcı metodunda olmalıdır.

Yukarıdaki örnekte ilgili sınıfın ilk ataması yapıcı metot sayesinde oluyor ancak bu değerlerin anlamlı olabilmesi için gönderilen parametreleri sınıfın özelliklerine set etmeliyiz. Bunun için ya ilgili sınıfın içinde bu yöntemi yapacağız ya da yapıcı metot aracılığı ile üst sınıfa bu değerleri gönderip üst sınıfta ilgili değerleri ilgili özelliklere set edeceğiz. Bizler ikinci yöntemi yapıyor olacağız.

Türemiş sınıfın yapıcı metodundaki değerleri temel sınıfın yapıcı metoduna aktarmak için base anahtar sözcüğü ile yapacağız. base ile bildirilen parametreler üst sınıfın yapıcı metoduna aktarılacaktır.

Yukarıda örneği test edebilmek için ayrıca temel sınıf Mammal’a ShowInfo() metodu ekledik. Bu sayede ilk değer ataması olan özellikleri ekrana yazdırıp kontrol edebiliyoruz.

Şimdi ise birden fazla türemenin olduğu bir yapının hiyerarşisine bakalım. Bunun için ihtiyacımız olan Dog sınıfından türeyebilen bir sınıf oluşturmamız.

Daha öncesinde gördüğümüz gibi sınıf hiyerarşisinin en tepesinde bulunan sınıftan başlayarak ( her sınıfta yapıcı metot tanımlı varsayılıyor) hiyerarşinin en alt sınıfının yapıcı metotları çağrıldı.

İsim Saklama (Name Hiding)

Türemiş sınıfta ihtiyaca göre bazen temel sınıftaki bir üye elemanla aynı isimli bir eleman tanımlamak isteyebiliriz. Bu tür durumlarda aynı isme sahip özelliği türemiş sınıfa eklemek için new anahtar sözcüğünü özellik için bildirmemiz gerekiyor.

SpecialDog sınıfına da temel sınıfta tanımlı olan Type özelliğini tekrar tanımlıyoruz.

Türemiş sınıf olan SpecialDog üzerinde aynı özelliği eklediğimiz taktirde Console uygulamasında test ederken derleyici bize temel sınıftaki Type özelliğinin türemiş sınıftaki Type özelliği tarafından gizlendiğini söylüyor. Bu yüzden yukarıda da bahsettiğimiz gibi new anahtar sözcüğünün kullanılmasını öneriyor. Buna rağmen program derlenecek-tir. Ancak biz her zaman isim gizlemesi yaparken isim gizlemeyi açıkça belirtmek için temel sınıftaki bir elemanı gizlerken türemiş sınıftaki elemanın bildirimine new anahtar sözcüğünü eklemeliyiz.

Bu şekilde tekrar çalıştırdığımızda kaynak kod uyarı vermeyecektir. İsim gizleme işlemini metotlar ve diğer üye yapılar içinde yapmak mümkündür.

Gereksinime göre oluşan isim gizleme durumlarında temel sınıfın aynı üye elemanına ulaşmak için base anahtar sözcüğüne kullanılır. Bu anahtar aslında sınıflarda kullanılan this referans benzemektedir. this anahtar sözcüğü kendisini çağıran sınıfı temsil ederken base anahtar sözcüğü türetmenin yapıldığı temel sınıfı ifade eder.

Yukarıdaki örnekte SpecialDog sınıfından bir nesne ürettik ve türünü (type) “Special Type” oalrak bildirdik. Console uygulamasını çalıştırdığımızda ekrana “Special Type” yerine “Golden” yazdığını göreceksiniz çünkü base anahtar sözcüğü ile GetBaseType() özelliği temel sınıftaki tür (type) özelliğini alıyor.

Temel ve Türeyen Sınıf Nesneleri

C# dili tür güvenliğine büyük önem vermektedir. (type-safe). Bu yüzden farkı türdeki nesnelerin birbirine özel durumların dışında atanması yasaklanmıştır. Bunun bir istisnası da temel ve türeyen sınıflarda görülmektedir. Türeyen sınıfa ilişkin bir referans temel sınıfa ilişkin bir referansa atanabilir. Daha önce yaptığımız Mammal ve Dog sınıflarını düşündüğümüzde Her Dog aslında bir Mammal’dır. Bundan dolayı her Dog nesnesini Mammal nesnesine ataya bilmemiz doğaldır.

Yukarıdaki örnekte Dog nesnesi Mammal nesnesine atayabildik. Ama defaultMammal referansı üzerinden Dog nesnesinin bütün özelliklerine erişmek mümkün değildir. Çünkü Mammal sınıfı Dog sınıfının üye elemanları ve metotlarından haberdar değildir. Bu yüzden atama yapmamıza rağmen sadece Mammal sınıfının üye elemanları ve metotlarına ulaşabiliriz.

Şimdi Dog sınıfına bir metot ekleyelim ve referansının atandığı defaultMammal üzerinde o metoda ulaşmaya çalışalım.

Yukarıdaki örnekte defaultMammal referansı üzerinden Dog sınıfının metodu olan TurnDog metoduna ulaşılamaz. Bunun sebebi daha önce söylediğimiz gibi temel sınıf olan Mammal’ın Dog sınıfı hakkında bir bilgiye sahip olmaması.

Temel ve Türeyen sınıflar arasındaki nesne yönelimli programlama tekniğin en önemli kavramlarından biri olan çok biçimliliğin (polymorphism) alt yapısını oluşturur. Çok biçimliliği Temel ve Türeyen sınıf üzerinden örnekle açıklamaya çalışalım.

Temel sınıf nesnesine türeyen sınıf nesnesi atayabildik. Aslında buda bir çok biçimlilik. Çünkü bu sayede nesne farklı bir biçimde davranıyor. Mammal türünde bir metot tanımlayalım.

Yukarıdaki örnekte statik metot olan ShowInfo Mammal türünden parametre bekliyor. Dog sınıfı Mammal sınıfından türediği için Dog türünden bir referansı metoda parametre olarak gönderebiliyoruz. Ancak bu metot içinde sadece Mammal sınıfının üye elemanlarına ulaşabiliriz. Bu sayede temel sınıf ile türeyen sınıflar arasında çok biçimliliği sağlamış oluyoruz.

Sanal Metotlar

Sanal metotlar temel sınıflar içinde bildirilmiş ve türeyen sınıflar içinde de tekrar bildirilen metotlardır. Sanal metotlar nesne yönelimli programlama tekniğindeki çok biçimliliği (polymorphism) uygulayan yapılardır. Temel sınıfta bir sanal metot bildirildiğinde temel sınıftan türeyen sınıflar, temel sınıfın bildirdiği metodu devre dışı bırakarak kendilerine uygun metot gövdesi oluşturabilirler. Sanal metotların en önemli özelliği daha önceden de bahsettiğimiz geç bağlam (late binding) özelliğidir.

Sanal metot hiyerarşisi nasıl çalışıyor? Temel sınıftan en alt türemiş sınıfa doğru bir çalışma mekanizması var. Tabi burada her türemiş sınıf temel sınıfların ilgili metodunu devre dışı bıraktığını varsayıyoruz. Yani temel sınıf türünde bir referansa türeyen sınıf referansları aktarıldığında, temel sınıf referansı üzerimden türeyen sınıfın sanal metodu çağrılır. Eğer türeyen sınıf sanal metodu devre dışı bırakmamışsa temel sınıftaki sanal metot çağrılır. Çağrılan metotlar hangi türe ait olduğu derleme aşamasında değil çalışma zamanında belli olur. Metotların bu şekilde çalışma zamanında belirlenmesine geç bağlama (late binding) denilmektedir.

Sanal metotlar virtual anahtar sözcüğü ile kullanılarak bildirilirler. Türeyen sınıflar temel sınıftaki sanal metotları devre dışı bırakmak için override anahtar sözcüğünü kullanırlar.

Sanal metotları pekiştirmek için örnek üzerinden gidelim.

Sanal metotlarr örnek üzerinden gidecek olursak; Mammal sınıfına ait Speak() metodunu ele alıp bu sınıftan türeyen Dog sınıfı içinde Speak() metodunu devre dışı bırakıp kendisine ait metot gövdesi oluşturalım.

Yukarıdaki örneğe baktığımızda Cat sınıfı temel sınıfın sanal metodunu devre dışı bırakıp kendine has özellikte bir metot gövdesi oluşturuyor ancak Dog sınıfı temel sınıfın sanal metodunu devre dışı bırakmıyor. Böylece Dog türünde bir nesne Speak() metodunu çağırdığında temel sınıfın belirlediği Speak() metodu çağrılıyor.

Çok çeşitlilik ve metotların devre dışı bırakılması ile ilgili özellikler

  • Eğer metotlar sanal olarak bildirilmemişse, derleyici nesnelerin tür bilgisinden faydalanarak derleme zamanında hangi metodun çağrılacağı bildirilir.
  • Eğer metotlar sanal olarak bildirilmişse, derleyici derleme zamanında ürettiği kod ile çalışma zamanında referans türüne göre ilgili sınıfın devre dışı bırakılmış metodu çağrılır
  • hangi metodun çağrılacağını çalışma zamanında belirlenmesine geç bağlama (late binding) denir
  • Sanal metotları bildirmek için virtual anahtar sözcüğü kullanılır
  • Türeyen sınıfta temel sınıftaki metodu devre dışı bırakmak için override anahtar sözcüğü kullanılır.
  • Türeyen sınıfta devre dışı bırakılan metotların temel sınıftaki sanal metotların ismi ile aynı olmalıdır.
  • Türeyen sınıfta devre dışı bırakılan metotların parametrik yapısı temel sınıftaki sanal metodun parametrik yapısı ile aynı olmalıdır.
  • Statik metotlar sanal olarak bildirilemez.
  • Türeyen sınıflar, temel sınıftaki sanal metotları devre dışı bırakmak zorunda değildirler.

Abstract (Özet) Sınıflar

Hiyerarşinin en tepesinde bulunan sınıflar kendisinden türetilecek diğer sınıflar için ortak özellikleri bir arada toplayan bir arayüz gibi davranmasını isteyebiliriz. Yani en tepedeki sınıf diğer sınıfların hangi karakteristik özelliğe sahip olmalarını belirtmek isteyebiliriz.

abstract = özet

Özet sınıflar ya da özet metotlar abstract anahtar sözcüğü ile bildirilirler. Temel sınıf içinde belirtilen abstract metotların gövdeleri yoktur. Ancak temel sınıftan türeyen sınıflar bu abstract metodu devre dışı bırakmalıdırlar. Özet (abstract) metotlar sanal metotlar oldukları için ayrıca virtual anahtar sözcüğünü kullanarak sanal olduklarını belirtmeye gerek yoktur.

Özet sınıflar abstract anahtar sözcüğü kullanılarak bildirilir. Abstract sınıf türünden nesneler tanımlanamaz. Abstract sınıflar sadece kendinden türeyen sınıflar için arayüz oluştururlar. Abstract metotlar türemiş sınıflarda temel sınıfın özet metotlarını devre dışı bırakmalı ve kendi metot gövdesini oluşturmalıdır. Abstract metotlar abstract sınıflarda kullanılabilirler. Yani abstract özelliği olmayan bir sınıfta abstract metotlar kullanılamazlar. Diğer yandan Abstract sınıflarda abstract olmayan metotlar da bildirilebilir.

Diğer bir özellik ise abstract metotlar private olarak bildirilemezler. Mantıken abstract metotlar türemiş sınıflar tarafından devre dışı bırakılacağı için metotlar private olursa abstract metodu devre dışı bırakamazlar. Ama abstract metotlar public ya da protected olabilirler.

Metot ve sınıflar gibi özellikler de abstract yapıda olabilirler.

Abstract sınıflar ve metotlar ile ilgili özet

  • Abstract sınıflar türünden nesneler tanımlanamaz
  • Abstract sınıflar abstract metotlar içerebilirler. Abstract metotlar ancak abstract sınıflar içinde bildirilebilirler.
  • Abstract sınıflar sealed anahtar sözcüğü ile işaretlenemezler. sealed anahtar sözcüğü bir sınıftan türetme yapılamayacağını belirtir.
  • Abstract sınıftan türeyen sınıflar temel sınıftaki bütün abstract metotları uygulamalıdırlar.
  • Bir abstract metot ancak özet sınıf içinde bildirilebilir.
  • Bütün abstract sınıflar içsel olarak sanaldır. Bu yüzden ayrıca virtual olmalarına gerek yoktur.
  • Static metotlar abstract olarak bildirilemezler. Aynı şekilde abstract metotların bildiriminde override ya da virtual anahtar sözcük kullanılmaz
  • Sınıflarda abstract özellikler de bildirilebilir, türeyen sınıflarda bu özet özellikler override anahtar sözcüğü ile tekrar bildirilmelidir.

sealed Anahtar Sözcüğü

Bazı durumlarda sınıfların türetilmesine engel olmak isteriz. Bunun birçok sebebi olabilir. Birincisi gerçekten de sınıftan türetme yapmak anlamsız olabilir, ikincisi güvenlik sorunları olabilir.

sealed anahtar sözcüğünün sınıflarda kullanımı

sealed anahtar sözcüğü özellikle bütün metotları statik olan sınıflar için gerçekten uygun görünür. Bütün metotları statik olan sınıftan türetme de çok fazla anlamlı olmayacaktır.

Interface (Arayüzler)

Interface (arayüz) diğer sınıflar için arayüz görevini taşır. Arayüzlerin bütün metotları ve özelliklerinin özet olarak bildirilmiş sınıflardan çokta farkı yoktur. Dolayısıyla arayüzlerde metotların ve özelliklerin gövdesi yazılmaz. Kısaca arayüzler, kendisini uygulayan sınıfların kesin olarak içereceği özellikleri ve metotları belirler.

Arayüzler genellikle birden fazla firmanın ya da programcının üzerinde çalıştığı projelerde ortak bir zemin oluşturabilmek için arayüzlerden faydalanılır.

Arayüzler interface anahtar sözcüğü kullanılarak bildirilir.

Bir arayüzde özellik, metot, indeksleyici veya temsilci (delegate) ve olay (event) bildirimi yapılabilir. Arayüz isimleri genellikle I harfi ile başlar ancak bu zorunlu değildir.

Arayüz bildirimi ile ilgili bilmemiz gereken kısıtlar ise;

  • Arayüzdeki elemanları statik olarak bildirmeyiz
  • Arayüzdeki eleman bildirimleri içsel olarak public oldukları için ayrıca bir elemanı erişim belirleyicisi ile bildirmek yanlıştır.
  • Arayüzler herhangi bir üye değişken içermez
  • Arayüzlerde yapıcı veya yıkıcı metotlar bildirilemez ya da tanımlanamaz.

IMammal arayüzünü uygulayan bir sınıfta Arayüzde bulunan bütün elemanların uygulanması gerekir. Buna göre Mammal sınıfı IMammal Arayüzünün bütün elemanlarını uygular.;

Sınıflar arasında çoklu türetme olmamasına rağmen sınıflar birden fazla arayüzü de uygulayabilir. Uygulanacak arayüzler virgül ile belirtilir.

Bir arayüzü uygulayan sınıfın sadece arayüzdeki elemanlara sahip olabileceği anlamına gelmez. Sınıfın kendine özgü elemanlara sahip olabilir.

Sınıflar birbirinden nasıl türetilebiliyorsa Arayüzlerde birbirinden türetilebilir. Temel arayüzdeki bütün elemanlar türeyen arayüze aktarılır. Böylece istediğimiz kadar eski arayüzü kullanarak daha geniş arayüzleri oluşturabiliriz.

Yukarıdaki Arayüz hiyerarşisine göre IMammal arayüzünü uygulayan sınıflar sadece IMammal arayüzündeki elemanları bildirirken, IHerbivorous arayüzünü uygulayan sınıflar Hem IMammal arayüzünü hem de IHerbivorous elemanlarını bildirmelidirler.

Arayüzleri türetirken new anahtar sözcüğü kullanılarak temel arayüzdeki elemanlar gizlenebilir.

Yukarıdaki arayüzü uygulayan bir sınıf Speak() metodunu uyguladığında ne olacak? Cevap basit geçerli bir bildirim olmayacak. Çünkü Speak() metodu gizlenmiş olsada türeyen arayüze aktarılmıştır. O yüzden böyle bir gereksinime ihtiyaç varsa arayüzleri explicitly olarak uygulamalıyız. Yani elemanlar hangi arayüze ait ise o arayüzün adı “.” özellikler ile uygulamalıyız.

Diğer bir soru ise DefaultMammal sınıfından bir nesne üzerinden Speak() metoduna ulaşabilir miyiz? Cevabımız hayır! Çünkü nesne üzerinden bu metodu çağırmaya kalktığımızda hangi arayüze ilişkin metodun çağrıldığı belli değildir.

Speak() metodunu çağırabilmek için açıkça hangi arayüzün Speak() metodunu çağırdığımız bildirmemiz gerekiyor.

Arayüz Referansları

Arayüzler ile referans oluşturulabilir. Böylece arayüzleri uygulayan herhangi bir sınıf nesnesini referansı atanabilir.

Açık (Explicit) Arayüz Uygulama

C# dilinde arayüzler uygulamanın diğer bir yolu ise Explicit Interface Implementation.

Bu yöntem;

  • Türeyen sınıflarda arayüzde bulunan üye elemanları açık bir şekilde nesneler tarafından erişemez hale getirilirler.
  • Birden fazla arayüz uygulandığı zaman eğer aynı isimli üye elemanlar varsa isim çakışmasının önüne bu yöntem ile geçilir.

Yukarıdaki örnekte IHerbivorous arayüzü IMammal arayüzünün Speak() metodunu gizlemiş ve DefaultMamaml sınıfına arayüz explicit yöntemle uygulanmıştır. İki arayüzde Speak() metodu var olduğu için hangi arayüzünün Speak() metotları çağrılacağı bildirilmelidir.

Partial (Kısmi) Tipler

C# 2.0’dan itibaren tip bildirimleri (sınıf, struct ya da interface) tek bir dosya içinde olmak zorunda değildir. Bir sınıftaki üye elemanları farklı kod dosyalarında yazma imkanına sahibiz. Bir sınıfın üye elemanlarını farklı bir kod dosyasında bildirebilmek için C# dilinde partial adında yeni bir anahtar eklenmiştir. partial olarak bildirilen sınıflar birden fazla kod dosyasında olabilir. Tabi bir sınıfın birden fazla kod dosyasında yer alması birden fazla örneği olması anlamına gelmiyor.

Derleme aşamasında partial olarak bildirilen bütün aynı isimli sınıflar yine tek bir çatı altında birleşmektedir. Sınıflarda metot aşırı yükleme ve yapıcı metot aşırı yükleme için olan kurallar burada da geçerlidir. Kısacası imzası aynı olan iki metot partial tip içinde tanımlanırsa derleme hatası meydana gelecektir.

Önemli Not: Derleme zamanında bütün aynı isimli partial sınıflar birleştirilerek tek bir tür olarak ele alınırlar.

Yukarıdaki örnekte aynı isme sahip 2 partial tipli Product sınıfları mevcuttur. Program derlendiğinde iki Product sınıfı tek bir çatıda birleşip aslında tek bir Product sınıf türü ve elaman üyeleri oluşturuluyor.

partial olarak tanımlanan tiplerin herhangi birinde abstract ya da sealed tanımı yapıldığında diğerlerinde aynı tanım yapmaya gerek yoktur. Herhangi birinde yapılan abstract ya da sealed tanımı sınıfın tamamı için geçerlidir.

Bu yazımda Nesne Yönelimli Programlama tekniği ve C# programlama dili ile bu tekniği uygulayabilmek için bilmemiz gereken temel kavramlar hakkında elde ettiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur.

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik,

https://docs.microsoft.com/tr-tr/dotnet/csharp/programming-guide/concepts/object-oriented-programming

Leave a Comment