Clear        


                
                    using _10_VirtualMethods.Demos.KdvHesaplama;
using System.Globalization;

namespace _10_VirtualMethods
{
    internal class Program
    {
        // Virtual methods (sanal methodlar) kalıtımda sub (child) class'larda override (ezmek, base methoddaki implementation'ını değiştirmek)
        // etmek için base (parent) class'ta istenilen methodlara virtual yazılarak kullanılır.
        // Amaç base class'ta default olarak implemente edilen bir method davranışının ihtiyaca göre sub class'larda değiştirilmesini sağlamaktır.
        // Sub class'larda virtual tanımlanmayan methodlar ezilemez.
        // Genelde pek yapılmasa da özellikler de virtual tanımlanabilir.



        static void Main(string[] args)
        {
            #region Virtual Methodlar
            // tipi Kopek olan referans değişkeni üzerinden Kopek tipinde obje initialize edilirken özelliklerinin atanması
            Kopek kopek = new Kopek()
            {
                Adi = "Leo Jr.",
                Cinsiyeti = Cinsiyet.Erkek,
                DogumTarihi = DateTime.Parse("19.10.2022", new CultureInfo("tr-TR")), // new DateTime(2022, 10, 19) da yazılabilir
                Irki = "Shetland Sheepdog"
            };

            Console.WriteLine($"Köpek:\nAdı: {kopek.Adi}\nCinsiyeti: {kopek.Cinsiyeti}\nIrkı: {kopek.Irki}\nDoğum Tarihi: {kopek.DogumTarihi.ToShortDateString()}");
            // short date string: kısa tarih formatı (bilgisayarın bölgesel ayarına göre örneğin Türkçe yani gün.ay.yıl veya İngilizce yani ay/gün/yıl)

            kopek.Uyu(); // base class'tan miras alınan method
            kopek.YemekYe(); // base class'tan miras alınan method
            kopek.SesCikar(); // base class'tan miras alınan ancak sub class'ta override edilen method

            Console.WriteLine();


            // tipi Kedi olan referans değişkeni üzerinden Kedi tipinde obje initialize edilmesi ve daha sonra özelliklerinin atanması
            Kedi kedi = new Kedi();
            kedi.Adi = "Angel";
            kedi.Cinsiyeti = Cinsiyet.Dişi;
            kedi.DogumTarihi = DateTime.Parse("05.09.2022", new CultureInfo("tr-TR"));
            kedi.Irki = "Ankara Kedisi";

            Console.WriteLine($"Kedi:\nAdı: {kedi.Adi}\nCinsiyeti: {kedi.Cinsiyeti}\nIrkı: {kedi.Irki}\nDoğum Tarihi: {kedi.DogumTarihi.ToShortDateString()}");

            kedi.Uyu(); // base class'tan miras alınan method
            kedi.YemekYe(); // base class'tan miras alınan method
            kedi.SesCikar(); // base class'tan miras alınan ancak sub class'ta override edilen method

            Console.WriteLine();
            #endregion



            #region Object Class'ı ToString() Virtual Methodu
            // C# Programlama Dili'nde tüm class'ların otomatik miras aldığı Object class'ındaki (veya object tipindeki) methodlardan biri ToString() methodudur.
            // Virtual olan bu method objenin string gösterimidir.
            // Eğer herhangi bir class'ta override edilmezse bu method çağrıldığında obje class'ının namespace'i ile birlikte adını (objenin tipi) döner.
            // İstenirse herhangi bir class'ta override edilerek objenin alan, özellik veya methodları kullanılarak obje ile ilgili özelleştirilmiş string dönülebilir,
            // böylelikle class'ta obje verilerini göstermek için ekstradan bir method oluşturmaya gerek kalmaz.

            Console.WriteLine(kopek); // Kopek class'ında ToString methodunu özelleştirmediğimizden konsola obje tipini yani "_10_VirtualMethods.Kopek" yazdırır

            Console.WriteLine();

            Console.WriteLine(kedi); // Kedi class'ında ToString methodunu özelleştirdiğimizden bu method çalışır ve özelleştirdiğimiz string dönerek kedi bilgisini yazdırır,
                                     // Console.WriteLine(kedi.ToString()); olarak da yazılabilir
            #endregion



            #region Demos
            KdvHesaplamaDemo.Calistir();
            #endregion
        }
    }



    enum Cinsiyet
    {
        Dişi,
        Erkek
    }

    class EvcilHayvan // base (parent) concrete (somut) class
    {
        #region Properties
        public string Adi { get; set; } // adi tüm evcil hayvanlar için ortak bir özellik
        public Cinsiyet Cinsiyeti { get; set; } // cinsiyeti tüm evcil hayvanlar için ortak bir özellik
        public DateTime DogumTarihi { get; set; } // doğum tarihi tüm evcil hayvanlar için ortak bir özellik
        public string Irki { get; set; } // ırkı tüm evcil hayvanlar için ortak bir özellik
        #endregion

        #region Behaviors
        public void YemekYe() // yemek yeme tüm evcil hayvanlar için ortak bir davranış
        {
            Console.WriteLine("Evcil hayvan yemek yiyor.");
        }

        public void Uyu() // uyuma tüm evcil hayvanlar için ortak bir davranış
        {
            Console.WriteLine("Evcil hayvan uyuyor.");
        }

        public virtual void SesCikar() // ses çıkarma tüm evcil hayvanlar için ortak bir davranış,
                                       // ancak sub (child) class'larda köpek ve kedi farklı sesler çıkardığından
                                       // ezmemiz gerekecek, bu yüzden methodu virtual tanımladık
        {
            Console.WriteLine("Evcil hayvan ses çıkarıyor.");
        }
        #endregion
    }

    class Kopek : EvcilHayvan // sub (child) concrete (somut) class, köpek bir evcil hayvandır (is-a relationship)
    {
        // EvcilHayvan base class'ındaki tüm özellikler ve methodlar kalıtım yoluyla bu sub class'a aktarılır

        // satırda override boşluk yazıldıktan sonra base class'ta virtual tanımlanmış method veya özellik
        // listesi üzerinden istenilenler override edilebilir (ezilebilir)
        public override void SesCikar()
        {
            //base.SesCikar(); // Otomatik olarak oluşturulan base method çağrımını her zaman kullanmak zorunlu değildir.
                               // base demek bu class'ın miras aldığı class (EvcilHayvan) demektir
                               // (daha doğrusu base tipten initialize edilen obje demektir),
                               // this demekse bu class (Kopek) demektir
                               // (daha doğrusu bu class tipinden initialize edilen obje demektir).
                               // Eğer bu class'ın methodu çağrıldığında base class'ın SesCikar methodu da çağrılmak isteniyorsa
                               // o zaman base.SesCikar(); yazılabilir. Bu durumda
                               // konsola "Evcil hayvan ses çıkarıyor." ve bir alt satırında da "Köpek havlıyor." yazdırılacaktır.
                               // Ancak bizim buradaki amacımız EvcilHayvan base class'ındaki SesCikar methodunu Kopek class'ında
                               // ezip özelleştirmek olduğundan base class'taki methodu çağırmıyoruz. Bu durumda
                               // konsola sadece "Köpek havlıyor." yazdırılacaktır.
                               

            Console.WriteLine("Köpek havlıyor.");
        }
    }

    class Kedi : EvcilHayvan // sub (child) concrete (somut) class, kedi bir evcil hayvandır (is-a relationship)
    {
        // EvcilHayvan base class'ındaki tüm özellikler ve methodlar kalıtım yoluyla bu sub class'a aktarılır

        // eğer base class'ta virtual tanımlanmış SesCikar methodu override edilmezse obje üzerinden bu method çağrıldığında base class'taki method çalışır,
        // ancak amacımız kedi miyavladığı için bu methodu ezmek ve özelleştirmek olduğundan override ediyoruz
        public override void SesCikar()
        {
            Console.WriteLine("Kedi miyavlıyor.");
        }

        // Object class'ındaki ToString() methodunu ezerek istediğimiz özelleştirilmiş kedi verilerini string olarak dönebiliriz
        public override string ToString()
        {
            return $"Kedi Bilgisi:\nAdı: {Adi}\nCinsiyeti: {Cinsiyeti}\nIrkı: {Irki}\nDoğum Tarihi: {DogumTarihi.ToShortDateString()}";
        }
    }
}