Merhaba direk bu sayfaya gelenler için belirteyim, bu yazı serinin dördüncü yazısı. Önceki bölümler için
https://ujk-ujk.blogspot.com/2023/01/c-temelleri-1.html ve
https://ujk-ujk.blogspot.com/2023/02/c-temelleri-2.html ve
https://ujk-ujk.blogspot.com/2023/02/c-temelleri-3.html
sayfalarına bakınız.
En son artık ağır konulara gireceğimizi belirtmiştik, hadi başlayalım.
C# Sınıf Tanımları (class)
Sınıflar bir konu ya da bir şeyle ilgili kodlarımızı bir arada topladığımız bloklardır. Daha önce hazır sınıf örnekleri kullandık. Mesela Console sınıfı içinde tanımlanmış ReadLine(), WriteLine() gibi metodları kullandık. Math sınıfı içinde tanımlanmış Pow(), Sqrt() gibi metodları kullandık. String sınıfının Length özelliğini kullandık vs.
Sınıflar içinde bir nesne üretmek ve kullanmak için gereken kodlar bir araya toplanır. Mesela bir String değişken oluşturduğumuzda aslında String sınıfı yapısına sahip bir nesne (object) oluşturuyoruz. Daha sonra oluşturduğumuz bu değişken üzerinde String sınıfının metodlarını uyguluyor ve özelliklerini kullanıyoruz. C# ve benzeyen bir çok programlama dili böyle sınıf yapıları üzerine kurulmuştur ve bu sınıflardan üretilen nesneler kullanılarak program yazarız. Bu şekil programlamaya nesne tabanlı programlama (object oriented programming - OOP) denir.
Programlarımızı içine yazdığımız Main() metodu da Program sınıfı içinde tanımlanmıştır.
Biz de kendi sınıflarımızı tanımlayıp onlardan ürettiğimiz nesneleri kullanabiliriz ya da bu sınıflar içinde metodlar tanımlayıp kullanabiliriz. Sınıf tanımlarken aynı bulunduğumuz dosya içerisinde Program sınıfına benzer şekilde ama dışında arkasına ekleyerek tanımlayabileceğimiz gibi, tamamen ayrı bir dosya içinde kendi sınıfımızı tanımlayabiliriz. Burada ayrı dosya olup olmaması için en çok bakılan kriter programın uzunluğudur, programınız çok uzun oluyorsa ayrı dosyada sınıf tanımı yaparsınız. Her iki yöntemi de göreceğiz.
Örnek olarak yararlı olacağını düşündüğümüz bazı mesajları veren metodları içeren bir sınıf tanımlaması yapalım.
Bu metodları kullanmadan önce yapıya bir bakalım, aynı yukarıda hazır bulduğumuz Program sınıfı gibi bir tanımlama yaptık ve içine metod tanımlamalarımızı koyduk. Peki bunları ayrı bir dosya içinde tanımlamak istersek?
Visual Studio editörde sağ üst köşede Çözüm Gezgini vardı (Solution Explorer) burada proje adımızın üzerine sağ tıklayıp Ekle ve Sınıf seçelim.
İngilizce olursa Add ve class.. tıklanır. Karşımıza projeye bileşen eklemek için bir pencere çıkar. Burada dosya adı olarak mesela Mesajlar girelim.
Ekle butonunu tıkladığımızda çözüm gezgininde yeni bir dosya eklendiğini görürüz. Adı Mesajlar.cs ve dosya editörde otomatik olarak açılır.
Dikkatimizi Mesajlar yazısı altındaki kırmızı uyarı çizgisi çeker. Kursörü üzerine götürürsek zaten CSharpTemelleri isim alanı içinde Mesajlar diye bir sınıf tanımı var diyecektir. Bu daha önce aynı dosya içinde yaptığımız sınıf tanımı ile çakıştığını anlatıyor. Şimdi orada tanımladığımız metodları buraya kopyalayalım ve Program.cs dosyası içindeki sınıf tanımını silelim.
Gelelim bu yazdığımız metodları nasıl kullanacağımıza. İki değişik yöntem kullandık daha önce hiç farketmeden. Bir tanesi sınıftan bir nesne üretmek ve o nesnenin metodlarını kullanmaktı. Random sayı meselesini hatırlarsak.
Örneğinde olduğu gibi. Biz de deneyelim,
Ops! Bir sorun var. Bizim tanımladığımız metodlar yardım listesine gelmedi. Metodlarımızın dışarıdan erişilebilir olması için metod tanımları başına public (genel kullanıma açık) kelimesi eklememiz gerekiyor, yoksa metodlar sınıf tanımı içinde kullanılan yardımcı metodlar gibi kabul görür ve dışarıdan erişilemez. Mesajlar.cs dosyamıza geri dönelim ve metod tanımlarının başına public kelimelerini ekleyelim.
Artık metodlarımızı kullanabiliriz.
Metodları kullanmamızın ikinci yolu ise daha önce Math sınıfı metodlarında gördüğümüz gibi yeni nesne üretmeden direk kullanmaktır. Örnek
Metodlarımızı bu şekilde kullanmayı deneyelim.
Yine olmadı. Metodlarımızı yeni nesne üretmeden direk kullanabilmek için de hem sınıf tanımının başına hem de kullanmak istediğimiz metodların başına static kelimesi eklememiz gerekiyor. İlerde daha ayrıntılı göreceğiz , şimdilik sadece kelimeyi koyalım.
Bakarsak sıralamada Hoşçakal() metodu tanımında değişik yazdım , o da kabul ama teamül public static şeklinde yazılmasıdır. void kelimesinin yerini zaten değiştiremeyiz o metoddan ne tip veri döneceğini belirtiyor. Şimdi metodlarımızı kullanalım.
Çalıştıralım
Harika!. Peki şimdi önceden yaptığımız sınıftan bir nesne üreterek metodlarını kullanma yöntemi çalışır mı? Çalışmaz çünkü static olarak tanımlaması yapılan bir sınıftan nesne üretilmesine izin verilmez. İhtiyacımıza göre birini seçeceğiz. Bir konuda bize yardımcı olacak metodları toplayacağımız bir sınıf tanımı yapıyorsak static olarak tanımlarız. Ama bir nesne üretecek ve o nesnenin özelliklerini ve metodlarını kullanacaksak static olmayan sınıf tanımlaması yaparız. Örnekler yaptıkça göreceğiz.
C# Nesneler (Objects)
Konular karmaşıklaşmaya başladı. Ancak daha önce gördüğümüz ama ne olduğunu nasıl yapıldığını bilmediğimiz şeyleri öğrenmek de heyecan verici. Bir nesne demek programlamada bir sınıf tanımından üretilmiş nesne demektir. Bu nesnelere sınıfın oluşumu denir, bundan sonra çok kullanacağımız bir kavram. Nesneleri oluşturmak için sınıf tanımlamalarını kullanırız. Bu yapı aslında gerçek dünyadan esinlenmiş bir yapıdır. Etrafımızda bir çok nesneler var bilgisayar, koltuk, masa, televizyon vs.
Gerçek hayattan nesneleri kodumuzda da nesneler olarak ifade edebiliriz. Nesnelerin özellikleri vardır ve eylemleri vardır. Örneğin İnsan sınıfı tanımından kişiler oluşturabiliriz. Bu amaçla ilk önce bir sınıf tanımı yapmamız gerekiyor.
Fazla karmaşık işler yapmayacağımız için sınıf tanımımızı ayrı bir dosyada yapmaya gerek yok. Aynı dosya içinde Program sınıfı tanımı dışında ama CSharpTemelleri isim alanımız içinde İnsan sınıfını tanımlamaya başlayalım.
Demiştik ki nesnelerin özellikleri olur. Diyelim İnsan sınıfından üreteceğimiz kişi nesnelerinin isim ve yaş özellikleri olsun.
Tanımladık ama şimdilik bir değer vermedik. Bunlar üreteceğimiz nesnelerin özellikleri. Eylemler ise metodlardır. Bir İnsan oluşumu ne eylemlerde bulunabilir? (ya da bizim programımızda kullanmayı düşündüğümüz İnsan oluşumlarında biz hangi eylemleri yapmak istiyoruz?). Örnek olarak yemek yediği ve uyuduğunu düşünelim ve bunlar için de sınıf tanımımıza metodlar ekleyelim.
Kullanmaya başlayalım. Programımız içinde bir kişi nesnesi üretelim.
Fakat yine unuttuk, kişi1 nesnesinin özellikleri ve metodlarına erişemiyoruz. Erişmek için başlarına public kelimesi koymalıyız.
Şimdi kişi1 nesnemizin özelliklerine değer verip eylemlerini kullanabiliriz.
İnsan sınıfı tanımını bir kere yaptık ama kişi nesnelerinden istediğimiz kadar oluşturabiliriz. İkinci bir kişi oluşturalım.
ve çalıştıralım
Bunlar nesneler için ön bilgiler daha öğreneceğimiz çok şey var.
C# Nesne İnşa Ediciler (constructor)
Bir sınıftan bir nesne oluşumu üretirken girilmesi gerektiğini düşündüğümüz değerler girilerek üretilmesini sağlamak amacıyla constructor adı verilen inşa edici metodlar kullanılır. Bunlar sınıfın üretici metodlarıdır ve bu metod isimleri sınıf adı ile aynı olmalıdır.
Bir önceki örneğimizi düşünürsek önce kişi nesnelerini ürettik daha sonra isim ve yaş özelliklerine ayrı satırlarda değerler girdik. Bu değerler girilerek kişi nesnesinin üretilmesini istersek sınıfa üretici metod ekleriz, şöyle ki,
Artık yeni kişi üretirken değerler girmek zorundayız.
Bununla beraber, programı çalıştırırsak kişi nesnelerimizin özelliklerinin otomatik olarak verilmediğini görürüz.
Eğri oturup doğruyu konuşalım, programlama dilleri şu anda kafamızdan geçenleri anlayacak kadar zeki değiller. Biz orada sınıfın üretici metodunu tanımlarken isim diye bir String parametre var dedik diye "aaa benin sınıf tanımımda da aynı isimde özellik var demek ki yazılımcı bunu demek istiyor" diye çalışmazlar. Kurallar vardır , her şeyi açık ve net belirtmeliyiz.
Gönderilen parametre değerlerini özelliklere atamak için üretici metodumuz içine şunları yazalım.
Şimdi program doğru çalışacaktır. this.isim demek , bu üretici metod yeni nesne üretirken çalışacağından , o anda üretilen nesnenin isim özelliği demektir. Metoda parametre adı olarak farklı şeyler de verebiliriz, burada amaç sürekli değişik kelimeler bulmaya çalışmamak, ama ilk başlayanlarda çok kafa karıştırdığı da olur. Mesela,
şeklinde yazsak tabi ki yine çalışır ve biz de "ya işte parametre isim için isimP yazarak sınıf özelliğiisimden ayırdık" diyebiliriz. Bir şey daha belirteyim,
şeklinde yazabiliriz artık. Çünkü derleyici için tek bir isim tanımı kaldı ve this.isim dememize gerek kalmaz.
ama bu çalışmaz, derleyici hangi isim değişkeni kullanacağına şöyle karar verir, önce varsa metod parametresindeki isim değeri, sonra dışarı bakar. Parametrede de isim değeri olduğuna göre onu alır ve aynı değeri aynı yere atamak olarak algılar. Zaten bu konuyu da editörümüz bize uyarır.
Uzun lafın kısası "biz işimizi kış tutalım, yaz çıkarsa bahtımıza" deyip this.isim notasyonunu kullanalım.
Daha gelişmiş bir örnek için bir Araç nesnesi düşünelim. 4 özelliği olsun, markası, modeli, yılı ve rengi.
Sınıf tanımına bir üretici metod ekleyelim ve bir de eylem ekleyelim.
Şimdi Araç sınıfımızın bir oluşumunu üretelim ve kullanalım.
ve sonuç,
İkinci bir araç nesnesi üretelim,
Üretici metodlar hakkında daha söylenecekler var ama biraz ilerdeki konularda göreceğiz.
C# static Kelimesi
static kelimesini daha önceden hatırlıyoruz. Mesela sınıf metodlarına nesne üretmeden direk erişmek için sınıfı ve metod tanımlarının başına static kelimesi eklememiz gerekiyordu. Şimdi static kelimesinin başka bir kullanımını göreceğiz.
static kelimesi sınıftan üretilen nesnelere değil de sınıfın kendisine bağlı özellikleri tanımlamak için de kullanılır. Örnek olarak basit bir Araç sınıfı tanımı ve kullanımı ile başlayalım.
Farz edelim toplam kaç tane araç oluşumu ürettiğimizi bilmek istiyoruz. Bu durumda sınıf tanımı içinde bir yerde kaç tane oluşum nesnesi üretildiğini kaydetmemiz gerekiyor. Bunu static tanımlı özellik kullanarak yapabiliriz. Öncelikle static olmayan bir özelliğe toplam araç sayısını kaydetmeye kalkarsak ne olur görelim.
Dışarıdan erişebilmek için public tanımlanmış bir araçSayısı değişken değerini her yeni araç nesnesi üretildiğinde bir arttırıyoruz. Ana kodumuzda yaptığımızı test edelim,
çalıştırıp kontrol ettiğimizde,
2 olamamış, çünkü araçSayısı değişkeni üretilen nesnenin bir özelliğidir ve her yeni araç nesnesi üretildiğinde değer sıfırdan başlıyor. Özellik değerinin nesneye değil sınıfa bağlı olması için static olarak belirtmeliyiz.
ve artık nesnenin değil sınıfın bir özelliği olduğu için erişim şeklimizi de değiştirmeliyiz.
Zaten araç1.araçSayısı yazsak da çalışmayacak ve bize araçSayısı özelliğine sınıf adı ile erişebileceğimizi bildirecektir.
Daha önce hatırlarsak sınıf tanımlarında sınıfı static olarak tanımladığımızda o sınıftan artık bir nesne üretilemediğini gördük. Ancak buradaki gibi sınıf tanımı static değilken özellikleri ve metodları içinde istediğimizi static yapabiliyoruz. Örnek olarak bir de static metod tanımı yapalım.
ve ana kodumuzda bu metodu direk olarak kullanalım.
ve sonuç
Gördüğümüz gibi static olarak nitelendirilen özellik ve metodlar direk olarak sınıfa bağlanıyor ve nesne oluşumlarından bağımsız kullanılıyor.
C# Üretici Metodların Tekrarlanması (overloading constructors)
Daha önce metodların tanımlanmasında gördüğümüz gibi sınıf üretici metodları da tekrar tanımlamalar ile nesne üretiminde değişik yöntemler kullanabilirler. Örnek olarak pizza yapımını düşünelim.
Şimdi ana programda bir pizza nesnesi üretelim.
Ama diyelim biz üzerinde malzeme olmayan pizza yapmak istersek, o opsiyonu boş bırakamayız. Değer olarak "yok" ya da boş string girebiliriz ama biz burada örnek vermeye çalışıyoruz. malzeme değeri girilmeden de pizza nesnesi üretebilmek için üretici metoda ikinci bir tanım yaparız.
Yapmışken bir kaç olasılık ekledik. Artık malzeme olmadan da pizza nesnesi oluşturabiliriz.
Aklıma gelmişken burada bir kısaltma yapabiliriz. Derleyici Pizza sınıfından bir nesne üretmek istediğimizi bildiği için
şeklinde bir tanımlamayı da kabul edecektir. Gözünüze nasıl güzel geliyorsa onu kullanabilirsiniz.
C# Kalıtım Yoluyla Sınıf Tanımlama (inheritance)
Bir ana sınıfın özellikleri ve eylemlerini de kullanabilen ama kendine özgü özellik ve eylemleri olan sınıf tanımlamalarında kalıtım yöntemi (inheritance) ile ana sınıftan alt sınıflar üretiriz. Örnek olarak bir Araç sınıfını ana sınıf olarak tanımlayalım.
Her araç farklı özelliklere sahip olacakken eğer Araç sınıfından kalıtım yoluyla tanımlanırsa Araç sınıfının hız özelliği ve Git() eylemini ortak kullanırlar. Örnek olarak Araç sınıfından Otomobil, Bisiklet ve Tekne sınıflarını kalıtım yoluyla tanımlayalım.
Alt sınıfı tanımlarken ana sınıfın adını iki nokta üst üste işaretinden sonra ekliyoruz. Bu durumda 3 sınıf kalıtım yoluyla Araç sınıfından tanımlanmış olur ve Araç sınıfına ait hız özelliği ve Git() eylemi bu 3 alt sınıf için de geçerlidir. Şimdi bu sınıfların oluşum nesnelerini üretip test edelim.
Gördüğümüz gibi Araç ana sınıfına ait olan hız özelliği ve Git() eylemini otomobil nesnesi için de kullanabiliyoruz. Çalıştırırsak,
Örnek küçük tutulduğu için pek anlaşılmayabilir ama bir aracın sahip olabileceği yüzlerce özellik ve eylemi düşünürsek bunları tanımladıktan sonra bir otomobil ya da bisiklet için ortak olan bir çok şeyi tekrar tanımlama zahmeti ve karışıklığından kurtulmuş oluyoruz.
C# Soyut Sınıf Tanımları (Abstract Classes)
Soyut sınıf tanımları çoğunlukla ana sınıflar için kullanılır. Bahsi geçen sınıfın tanımının tam olarak bitmediği ve eksikleri olduğu için nesne oluşumunda kullanılamayacağını ifade etmek için kullanılır. Bir önceki Araç ana sınıfının değişik bir uygulamasını yapalım.
Şu andaki haliyle biz Araç ana sınıfından da bir nesne oluşturabiliriz.
Ama biliyoruz ki, Araç sınıfının eksik özellikleri var kaç tekerleği olduğunu ve maksimum hangi hızda gidebileceğini belirleyemiyoruz. Mesela programımızda bu araçları yarıştıracaksak bu eksik özellikleri yüzünden Araç sınıfından bir nesne oluşturulmasını istemeyiz. Bunu sisteme bildirmek için sınıf tanımı başına abstract kelimesini ekleriz.
abstract kelimesini Araç sınıfı tanımının başına eklediğimiz anda yukarıdaki kodda araç nesnesi üretilirken bir hata bildirimi gelecektir.
Diyor ki bu soyut bir sınıf ve bundan bir nesne oluşumu yapamazsın. Bu sayede kendimizi ve bizden başka aynı proje üzerinde çalışan yazılımcıları yanlış nesne üretmekten korumuş oluruz. Basit bir güvenlik önlemi.
C# Nesnelerden Oluşan Array
Daha önce array yapısını gördük, şimdi de nesnelerden oluşan bir array oluşturulması ve kullanımına bakalım.
Araç sınıfından birkaç nesne oluşturalım,
Bu araçları bir array içinde yerleştirmek istersek daha önce nasıl String değerlerden oluşan array tanımlarken String[] kullandıysak Araç değerlerden oluşan bir array tanımlamak için de Araç[] kullanırız.
Şimdi konsolda bir gösterimini yapalım,
Bu bize garaj[0] array elemanının veri tipini yazacaktır.
Nesnenin model özelliğini yazdırmak istersek,
Şeklinde yazarız. Hepsini bir foreach döngüsü ile yazmak istersek,
Array tanımlamasını direk değer girerek yapmak istersek nesne oluşumlarını array elemanları olarak gireriz.
Bu yazı da fazla uzadı editör teklemeye başladı bu kadarı ile yayınlayalım sonra devam edeceğiz. Kalın sağlıcakla..
Sonraki bölüm https://ujk-ujk.blogspot.com/2023/03/c-temelleri-5.html
Hiç yorum yok:
Yorum Gönder