Clear        


                
                    // Classes (Sınıflar)

namespace _01_Classes 
// namespace: uzay: class kümesi, class'ların dosya yerlerinden bağımsız proje içerisinde yerlerini ayarlamamızı sağlar.
// Genelde yeni eklenen klasör ya da dosyalar üzerinden otomatik oluşturulur.
// Başka namespace altındaki class'lara ya kendi namespace adları üzerinden ya da en yukarıda using kullanılarak erişilebilir.

{
    internal class Program
    {
        // Class'lar objelerin blueprint'leridir yani taslaklarıdır.
        // Genel anlamda çeşitli işlemleri gruplayarak gerçekleştirmemizi sağlar.
        // Oluşturulan class'lar referans tiptir, new'leme işlemi ile obje olşuturularak (instantiation) obje (instance) üzerinden class'ta tanımlananlar kullanılabilir.
        // Class'lar ender durumlar dışında diğer class'ların dışında oluşturulur.
        // Class isimlendirmelerinde Pascal Case, yani ilk kelimenin ilk harfi büyük, varsa diğer kelimeler bitişik ve ilk harfleri büyük uygulanır.
        // Class içerisindeki değişken isimlendirmelerinde Camel Case, yani ilk kelimenin ilk harfi küçük, varsa diğer kelimeler bitişik ve ilk harfleri büyük uygulanır ve _ ile başlanır.
        // Class içerisindeki method isimlendirmelerinde Pascal Case uygulanır.
        // Method içerisindeki parametre ve değişken isimlendirmelerinde ise Camel Case uygulanır.
        // Veri taşıyan class'lara Model (DTO: Data Transfer Object) veya Entity, verileri yöneten class'lara Repository (Repo),
        // iş yapan class'lara da Service (Manager) isimleri verilir.
        // Repository'lerle birlikte Entity'ler ve DTO'lar, Service'lerle birlikte de Model'ler kullanılır.

        // Hafıza (Memory) Tipleri:
        // 1) Stack Memory: Tüm değer tipler (bool, byte, char, decimal, double, enum, float, int, long, sbyte, short, struct, uint, ulong, ushort)
        // tarafından değerlerin tip ve değişken tanımları üzerinden saklandığı LIFO (Last In First Out, son giren ilk çıkar) yapıdaki statik
        // hafıza yönetimi yapılan hafızadır.
        // 2) Heap Memory: Tüm referans tipler (string, class, interface, delegate, object) tarafından değerlerin veya objelerin belirli bir sıra içerisinde olmayan
        // hafıza adreslerinde tutulduğu dinamik hafıza yönetimi yapılan hafızadır. Değer ve objelerin adresleri Stack Memory'de tip ve değişken tanımları ile
        // saklanarak Heap Memory'deki değer ve objelere bu adresler üzerinden erişilir, yani Stack Memory'deki değişkenler Heap Memory'deki değer ve objelere refere eder.



        static void Main(string[] args)
        {
            #region Insan Sınıfı (Obje Oluşturma ve Kullanma)
            Insan insan; 
            // Insan: sınıf yani tip, insan: değişken deklarasyonu

            insan = new Insan(); 
            // class üzerinden new'leme ile instance (obje) oluşturuyoruz. insan değişkeni artık Insan sınıfından türemiş bir objeyi refere eder,
            // insan değişkeninin refere ettiği objeyi new'leme ile initialize ettik.

            insan.SetAdi("Çağıl");
            insan.SetSoyadi("Alsaç");
            insan.SetYasi(42); // eğer sayısal tipler set edilmezse default (varsayılan) değerleri 0 olur.
            string adi = insan.GetAdi();
            string soyadi = insan.GetSoyadi();
            int yasi = insan.GetYasi();
            Console.WriteLine($"Soyadı: {soyadi}, Adı: {adi}, Yaşı: {yasi}"); // konsola "Soyadı: Alsaç, Adı: Çağıl, Yaşı: 42" yazdırır



            insan = new Insan(); 
            // yukarıdaki insan değişkeni üzerinden tekrar new'leme yapılırsa yukarıda daha önce refere edilmiş obje yerine
            // artık burada new'lenen obje insan değişkeni tarafından refere edilmeye başlanır,
            // yukarıdaki daha önce refere edilmiş objeye artık ulaşılamaz.

            insan.SetSoyadi("Alsaç");
            insan.SetAdi("Leo");
            insan.SetYasi(8);
            Console.WriteLine($"Adı ve Soyadı: {insan.GetAdi()} {insan.GetSoyadi()} ({insan.GetYasi()})"); // konsola "Adı ve Soyadı: Leo Alsaç (8)" yazdırır



            _01_Classes.Insan yeniInsan = new _01_Classes.Insan(); 
            // yeni bir Insan tipindeki yeniInsan değişkeninin refere ettiği bir instance (obje) new'ledik,
            // dolayısıyla şu anda elimizde iki tane Insan tipinde birbirinden ayrı obje oldu.
            // bu satırda namespace üzerinden Insan class'ına ulaştık.

            yeniInsan.SetAdi("Luna");
            yeniInsan.SetSoyadi("Alsaç");
            yeniInsan.SetYasi(1);
            string yeniInsanText = "Adı: " + yeniInsan.GetAdi() + "\nSoyadı: " + yeniInsan.GetSoyadi() + "\nYaşı: " + yeniInsan.GetYasi();
            Console.WriteLine(yeniInsanText); // konsola \n escape sequence'ı ile alt satırlara geçerek "Adı: Luna\nSoyadı: Alsaç\nYaşı: 1" yazdırır.
            yeniInsan.AdiVeSoyadiYazdir(); // konsola "Luna Alsaç" yazdırır
            #endregion
        }
    }



    #region Insan Sınıfı (Class Oluşturma)
    class Insan
    {
        string _adi; // field (alan): sadece bu class'a özel değişkenler, new'lenen obje üzerinden ulaşılamazlar, genelde başlarına _ konarak tanımlanırlar.

        string soyadi; // field, eğer değişken adının başına _ konulmazsa method içerisinde this (bu sınıf yani Insan) üzerinden ulaşılmalıdır, pek tercih edilmez.

        int _yasi; // field

        // alanlar istenilen bir tip (int, bool, DateTime, vb.) olarak deklare edilip kullanılabilir.

        // public tanımlanan değişken ve alanlar obje new'lendikten sonra referans değişkeni üzerinden kullanılabilir, tanımlanmayanlara ise ulaşılamaz.
        // public değişken kullanımı tercih edilmemelidir.

        public void SetAdi(string adi) // behavior (davranış): bu class'ın yapacağı işler, _adi alanının verisini new'lenen obje üzerinden atama (set) işini gerçekleştirir.
        {
            _adi = adi;
        }

        public string GetAdi() // behavior: yukarıdaki SetAdi methodu ile atanan _adi değişkeninin verisinin new'lenen obje üzerinden alınmasını (get) sağlar.
        {
            return _adi;
        }

        public void SetSoyadi(string soyadi) // behavior, setter, eğer parametre adı ile alan adı aynı ise mutlaka class'ın alanı için this kullanılmalıdır.
        {
            this.soyadi = soyadi;
        }

        public string GetSoyadi() // behavior, getter.
        {
            return soyadi; // burada this yazmaya gerek yoktur çünkü yukarıdaki soyadi alanı kullanılır.
        }

        public void SetYasi(int yasi) // behavior, setter.
        {
            _yasi = yasi;
        }

        public int GetYasi() // behavior, getter
        {
            return _yasi;
        }

        public void AdiVeSoyadiYazdir() // behavior, yukarıdaki setter ve getter methodları dışında istenilen işler ihtiyaca göre oluşturulan methodlar üzerinden gerçekleştirilebilir.
        {
            Console.WriteLine($"{_adi} {soyadi}"); // burada da this yazmaya gerek yoktur çünkü yukarıdaki soyadi alanı kullanılır.
        }
    }
    #endregion
}