Clear        


                
                    using _13_Polymorphism.Enums;
using _13_Polymorphism.Models;
using _13_Polymorphism.Models.Bases;
using System.Globalization;

namespace _13_Polymorphism
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // Polymorphism (poly: çok, morphism: değişim) base (parent) tipte bir referans değişkeni üzerinden istenilen sub (child) tiplerde objeler yaratılmasıdır.
            // Tek bir referans değişkeni üzerinden değişkenin tipini değiştirmeden ihtiyaca göre sub (child) tiplerde objeler yaratılıp kullanılabilir.



            VideoOyunu videoOyunu = new VideoOyunu() // videoOyunu referans değişkeninin tipi base tip, new'lenen objenin de tipi base tip,
                                                     // Red Dead Redemption 2 hem PC hem Playstation oyunu olduğundan base tip üzerinden oluşturduk,
                                                     // bu şekilde sadece bu oyunun VideoOyunu sınıfındaki özelliklerini kullanabiliriz
            {
                Adi = "Red Dead Redemption 2", // VideoOyunu class'ı özelliği

                //CikisTarihi = new DateTime(2018, 10, 26), // bu şekilde de atanabilir
                CikisTarihi = DateTime.Parse("26.10.2018", new CultureInfo("tr-TR")), // VideoOyunu class'ı özelliği

                // Flags attribute'u kullanımı sayesinde | ile oyunu hem tek hem çok oyunculu işaretlemiş oluyoruz
                OyuncuSayisi = OyuncuSayisi.TekOyuncu | OyuncuSayisi.ÇokOyuncu, // VideoOyunu class'ı özelliği

                Yapimcisi = "Rockstar Games", // VideoOyunu class'ı özelliği

                //Turleri = new string[4] // bu şekilde de atanabilir
                //{
                //    "Western", "Açık Dünya", "Aksiyon", "Macera"
                //}
                Turleri = new string[] // VideoOyunu class'ı özelliği
                {
                    "Western", "Açık Dünya", "Aksiyon", "Macera"
                }
            };

            // oyunu konsola yazdırıyoruz:
            Console.WriteLine("Oyun Bilgisi:\n" +
                $"Adı: {videoOyunu.Adi}\n" +
                $"Yapımcısı: {videoOyunu.Yapimcisi}\n" +
                $"Türleri: {videoOyunu.TurleriGosterim}\n" +
                $"Modlar: {videoOyunu.OyuncuSayisiGosterim}\n" +
                $"Çıkış Tarihi: {videoOyunu.CikisTarihi.ToString("dd.MM.yyyy")}"); // bilgisayarın bölgesel ayarı Türkçe ise videoOyunu.CikisTarihi.ToShortDateString() de yazılabilir



            #region PC Oyunu (Polymorphism)
            // yukarıda VideoOyunu tipinde tanımladığımız ve VideoOyunu tipinde bir objeye refere eden aynı değişken üzerinden PcOyunu tipinde bir obje new'liyoruz,
            // böylece artık videoOyunu değişkeni PcOyunu tipindeki objeyi refere etmeye başlar,
            // dolayısıyla base (parent) tip'teki variable'lar (değişkenler) üzerinden sub (child) tiplerdeki objeler ihtiyaca göre initialize edilebilir (oluşturulabilir)
            videoOyunu = new PcOyunu()
            {
                Adi = "Half-Life: Alyx", // VideoOyunu base class'ı özelliği
                CikisTarihi = DateTime.Parse("23.03.2020", new CultureInfo("tr-TR")), // VideoOyunu base class'ı özelliği
                OyuncuSayisi = OyuncuSayisi.TekOyuncu, // VideoOyunu base class'ı özelliği, tek oyunculu olarak işaretledik
                Yapimcisi = "Valve", // VideoOyunu base class'ı özelliği
                Turleri = new string[] { "VR", "FPS", "Bilim Kurgu" }, // VideoOyunu base class'ı özelliği

                IsletimSistemleri = new string[] { "Windows 10", "Windows 11" }, // PcOyunu sub class'ı özelliği
                SteamOyunuMu = true // PcOyunu sub class'ı özelliği
            };

            // PC oyununu konsola yazdırıyoruz:
            // referans değişkeninin tipi VideoOyunu olduğundan değişken üzerinden sadece VideoOyunu class'ı özelliklerini kullanabiliriz
            Console.WriteLine("\nOyun Bilgisi:\n" +
                $"Adı: {videoOyunu.Adi}\n" +
                $"Yapımcısı: {videoOyunu.Yapimcisi}\n" +
                $"Türleri: {videoOyunu.TurleriGosterim}\n" +
                $"Modlar: {videoOyunu.OyuncuSayisiGosterim}\n" +
                $"Çıkış Tarihi: {videoOyunu.CikisTarihi.ToShortDateString()}");

            // new'lenen objenin tipi PcOyunu olduğu için VideoOyunu tipindeki referans değişkeni olan videoOyunu'nu
            // PcOyunu tipine cast edip PcOyunu class'ı özelliklerini kullanabiliriz:

            //PcOyunu pcOyunu = (PcOyunu)videoOyunu; // 1. yöntem
            PcOyunu pcOyunu = videoOyunu as PcOyunu; // 2. yöntem

            // PC oyununun çalıştığı İşletim Sistemleri ile Steam oyunu bilgilerini konsola yazdırıyoruz:
            Console.WriteLine("PC İşletim Sistemleri:\n" + pcOyunu.IsletimSistemleriGosterim + "\nSteam Oyunu: " + pcOyunu.SteamOyunuMuGosterim);
            #endregion



            #region Playstation Oyunu (Polymorphism)
            // yukarıda VideoOyunu tipinde tanımladığımız ve en son PcOyunu tipinde bir objeye refere eden aynı değişken üzerinden PlaystationOyunu tipinde bir obje new'liyoruz,
            // böylece artık videoOyunu değişkeni PlaystationOyunu tipindeki objeyi refere etmeye başlar,
            // dolayısıyla base (parent) tip'teki variable'lar (değişkenler) üzerinden sub (child) tiplerdeki objeler ihtiyaca göre initialize edilebilir (oluşturulabilir)
            videoOyunu = new PlaystationOyunu()
            {
                Adi = "Gran Turismo 7", // VideoOyunu base class'ı özelliği
                CikisTarihi = new DateTime(2022, 3, 4), // VideoOyunu base class'ı özelliği
                OyuncuSayisi = OyuncuSayisi.ÇokOyuncu, // VideoOyunu base class'ı özelliği, çok oyunculu olarak işaretledik
                Yapimcisi = "Polyphony Digital", // VideoOyunu base class'ı özelliği
                Turleri = new string[] // VideoOyunu base class'ı özelliği
                {
                    "Yarış",
                    "Spor",
                    "Simülasyon"
                },

                Modelleri = new byte[] { 4, 5 } // PlaystationOyunu sub class'ı özelliği
            };

            // Playstation oyununu konsola yazdırıyoruz:
            // referans değişkeninin tipi VideoOyunu olduğundan değişken üzerinden sadece VideoOyunu class'ı özelliklerini kullanabiliriz
            Console.WriteLine("\nOyun Bilgisi:\n" +
                $"Adı: {videoOyunu.Adi}\n" +
                $"Yapımcısı: {videoOyunu.Yapimcisi}\n" +
                $"Türleri: {videoOyunu.TurleriGosterim}\n" +
                $"Modlar: {videoOyunu.OyuncuSayisiGosterim}\n" +
                $"Çıkış Tarihi: {videoOyunu.CikisTarihi.ToShortDateString()}");

            // new'lenen objenin tipi PlaystationOyunu olduğu için VideoOyunu tipindeki referans değişkeni olan videoOyunu'nu
            // PlaystationOyunu tipine cast edip PlaystationOyunu class'ı özelliklerini kullanabiliriz:

            //PlaystationOyunu playstationOyunu = (PlaystationOyunu)videoOyunu; // 1. yöntem
            PlaystationOyunu playstationOyunu = videoOyunu as PlaystationOyunu; // 2. yöntem

            // Playstation oyununun çalıştığı Playstation modelleri bilgisini konsola yazdırıyoruz:
            Console.WriteLine("Playstation Modelleri: " + string.Join(", ", playstationOyunu.Modelleri)); // string class'ının Join methodu ilk parametre olarak gönderilen
                                                                                                          // ayraca göre (", ") ikinci parametre olarak gönderilen koleksiyonun
                                                                                                          // (burada dizi: playstationOyunu.Modelleri) elemanlarını
                                                                                                          // concatenate ederek (art arda birleştirerek) string döner
            #endregion
        }
    }
}