22 Aralık 2017 Cuma

Visual Studio "Create Unit Tests" Menüsü


Visual Studio'da Unit Test yapmak istiyorsunuz fakat "Create Unit Tests..." menüsü gelmiyorsa ya da disable geliyorsa bunun çözümü için doğru yerdesiniz.

Eğer kodunuza sağ tıkladığınızda "Create Unit Tests" gelmiyorsa öncelikle bunun gelmesini sağlamalıyız.

1) Visual Studio > TOOLS > Customize

2) Açılan Customize ekranında Commands sekmesine gelin. Context menu radio butonunu tıklayın. Combodan "Editor Context Menus | Code Window" seçiniz. Gelen seçeneklerden "Create Unit Tests..." menüsünü bulun ve seçin. Sonra Close deyin.



Bu durumda kodunuzun her hangi bir yerinde sağ tıkladığınızda "Create Unit Tests..." menüsü gelecektir ama henüz test projeniz olmadığından aşağıdaki gibi disabled durumda gelebilir.


Yukardaki gibi disabled durumda geliyorsa test projesi olmadığındandır. Bu proje için bir test projesi oluşturmanız gerekmektedir.

1) FILE > Add > New Project deyip çıkan ekranda Installed > Visual C# > Test menüsünden yeni bir test projesi ekliyoruz.



2) Eklenen test projesine sağ tıklayıp Add > Unit Test diyoruz. 


Unit test yapmak istediğiniz kod sayfasına gelip sağ tıklayınca artık "Create Unit Tests..." menüsü aşağıdaki gibi enable olacaktır.



Şimdilik bu kısmını anlattık. Unit Test nedir nasıl yapılır konusunu ise başka bir yazıda ele alacağız.

Herkese iyi kodlamalar...


Paylaş:

28 Kasım 2017 Salı

Javascript'teki "===" Operatörü


Merhaba,

Javascript'te bazen şu "===" operatörü görmüşsünüzdür. Bu da ne ola ki diye merak ediyorsanız cevabı burada :)

Bildiğiniz üzere javascript esnek bir dile sahiptir. C# dili gibi katı tip denetimli bir dil değildir:

Lafı uzatmadan, aşağıdaki örneği inceleyelim. var x = 1; var y = "1"; if(x == y){ alert("Değişkenler aynı"); }else{ alert("Değişkenler aynı değil"); }

Yukardaki kod, "Değişkenler aynı" uyarısını verecektir.

Fakat bir adım daha ileriye gidip hem değişken değerleri hem de tip kontrolü yapmak istersek "===" operatörünü kullanmalıyız.


var x = 1; var y = "1"; if(x === y){ alert("Değişkenler aynı"); }else{ alert("Değişkenler aynı değil"); }

Bu sefer bu kod "Değişkenler aynı değil" uyarısını verecektir. Çünkü biri sayı değerinde (1) ötekisi de string ("1") değerindedir. Bir nevi C#'taki tip denetimi gibi.

Kodu şöyle  düzeltirsek,

var x = 1; var y = 1; if(x === y){ alert("Değişkenler aynı"); }else{ alert("Değişkenler aynı değil"); }

Bu sefer çıktı "Değişkenler aynı" olacaktır.

Benzer şekilde "!==" operatörü de tersini kontrol etmek amacıyla kullanılabilir. Değişken değeriyle birlikte tip kontrolü farklı olması kontrolü sağlanabilir.

Hepinize iyi kodlamalar...


Paylaş:

25 Kasım 2017 Cumartesi

C# interface Kavramı (Arabirimler)


Merhaba,

Size bu yazıda C#'ta önemli bir konu olan interface yapısından bahsedeceğim. Türkçe'deki diğer adı arabirimler. Bu yazıda interface terimini kullanacağım.

interface nedir?

interface, işlevselliği olmayan ama işlevselliği tarif eden, bir işin nasıl yapılacağını değil de ne yapılacağını tarif eden mantıksal bir özelliktir. Türkçe adından da anlaşılacağı üzere bir arabirimdir. abstract classların bir adım ileriye götürülmüş halidir. abstract classları hatırlayalım (abstract classların detayı için tıklayın) bazı metotların  gövdesi olmakla birlikte abstract metotların gövdesi yoktu. kalıtım yoluyla aktarıldığı sınıflarda uygulanmak zorundaydı. interface'de ise bütün metotlar gövdesizdir. Yani bir interfacei kalıtım yoluyla devralan bir sınıf interfacein bütün metotlarını uygulamak zorundadır. Bu, hem kod garantisi sağlar hem de hataları minimize eder. Hem de büyük projelerde bir prototip ortaya koymamızı sağlar. 

Bazen bir uygulamanın ana şablonlarını ortaya koymak istersiniz. Neler yapılacağını belirlersiniz fakat detaylarına girmezsiniz. Detayları size bağlı çalışanlarınız yapacaktır. İşte bu tam olarak interface tanımına uygundur. Alın size gerçek hayattan interfacelere örnek.. Diyelim ki siz bir işletmenin patronusunuz ve kakaolu kek yapacaksınız. Kakaolu kek için ne lazım? Kakao, un, şeker.. Bu üç malzeme olmazsa olmazdır. O zaman projenizde ne olmalı? KakaoGetir(), UnGetir(), SekerGetir()... Siz patsonsunuz ya, tabiki de siz markete gidip bunları temin etmeyeceksiniz. Hepsi de farklı marketlerde bulunabilir. Nihayetinde bu görevleri siz değil, size bağlı kişiler yapacaktır. Ahmet! Sen kakao getir. Mehmet! Sen de un getir. Veli e oğlum sen de şeker getir. Ahmet der ki: patron kakaoyu nerden alayım nasıl getireyim? Patron der ki ben karışmam getir ama nerden getirirsen getir, ister arabayla git ister yürüyerek ama istersen şu yandaki X marketinin ürünleri güzeldir ordan alabilirsin ama yeter ki bana getir der. Ahmet de allem eder kallem eder gider kakaoyu getirir. X marketinde bulamayıp Y marketine gider getirir ama getirir. Mehmet de yürüyerek yandaki bakkaldan un alır gelir. Veli de motora atlayıp kestirme yolunu en iyi bildiği marketten şeker alır gelir. Sonuç olarak kakao, un ve şeker, kekin olmazsa olmazıdır bu üç malzeme tamamlanmazsa kek ortaya çıkmayacaktır. Ahmet, Mehmet ve Veli üçü de görevini layıkıyla yerine getirip kekin yapılmasında büyük katkıları olmuştur.

Gelelim, kod olarak interfacelerin tanımına.. Genel olarak interface tanımı şu şekilde yapılır

interface ad {

          tip1 metot1 (parametre listesi);
          tip2 metot2 (parametre listesi);
          .
          .
          .
}

Dikkat edin, metotların gövdesi yoktur. Sadece dönüş tipi, metot adı ve metot parametrelerine sahiptir. Asıl iş, bu interfacei devralacak classlarda yapılacaktır. metotlar kapalı olarak publictir. Mantıklı olarak düşünüldüğünde, bir interfacei devralacak herhangi bir class içindeki tüm metotları uygulamak zorunda olduğuna göre bütün metotlara erişmek zorundadır. Dolayısıyla metotların neden kapalı olarak public olduğu anlaşılabilir.

interfaceler veri üyeleri içermezler, yapılandırıcı ve yok edicilere de (constructor, destructor) sahip olamazlar, ayrıca hiçbir üyesi static olamaz. Çünkü interfaceler classlar gibi nesne üretmezler sadece arabirimlerdir. interfaceleri uygulayan classların uygulayacağı interface'e ait metotlar da public olmak zorundadır. Aynı zamanda interfacei uygulayan metotların dönüş tipi, parametreleri birebir aynı olmak zorundadır.

interfaceler tanımlanırken, başına "I"  harfi konulması kodun okunulabilirliğini oldukça arttırır. Bu bir zorunluluk olmamakla birlikte, son derece yaygın bir kullanımdır. Böylece kalıtım aldığımız yapının bir interface olduğunu kolayca anlarız.

Aşağıdaki örneği inceleyelim:

interface ISayiSerileri {
        int SonrakiSayi();
        void Sifirla();
    }

    class CiftSayilar : ISayiSerileri {
                
        int val = -2;

        public int SonrakiSayi() {
            val += 2;
            return val;
        }

        public void Sifirla() {
            val = -2;
            Console.WriteLine("Sayaç sıfırlandı...");
        }

        public void CiftSayilariGetir(int adet) {
            StringBuilder sb = new StringBuilder ();
            for (int i = 0; i <= adet; i++)
            {
                sb.Append(SonrakiSayi() + ", ");
            }
            Console.WriteLine(adet + " adet çift sayı serisi" );
            Console.WriteLine(sb.ToString());
        }
    }

static void Main(string[] args)
        {
            CiftSayilar cs = new CiftSayilar();
            cs.CiftSayilariGetir(5);
            cs.Sifirla();
            cs.CiftSayilariGetir(7);
            Console.ReadLine();
        }

Bu programın çıktısı aşağıdaki gibi olacaktır:

5 adet çift sayı serisi
0, 2, 4, 6, 8, 10,
Sayaç sıfırlandı...
7 adet çift sayı serisi
0, 2, 4, 6, 8, 10, 12, 14,

Bu programı biraz daha inceleyelim: 

ISayiSerileri diye bir interface tanımladık. Bu interface iki tane metotda sahip:

int SonrakiSayi();
void Sifirla();

ISayiSerileri'deki tanımlara dikkat ediniz.. Herhangi bir erişim belirteci yok. Çünkü kapalı olarak publictir. Fakat bunu uygulayan CiftSayilar classındaki bu metotların tanımı publictir. public olmak zorundadır. CiftSayilar classında bu iki metottan birini çıkardığınızda derleme hatası alacaksınız. Uygulayıcı sınıflar interfacelerin bütün metotlarını uygulamak zorunda olmakla birlikte, ayrıca kendi üyelerine ve kendi metotlarına (CiftSayilariGetir(int adet)) sahip olabilirler.


Not: Daha önce kalıtım derslerinde yazdığım gibi, bir class yalnızca bir tane classı kalıtım yoluyla devralabiliyorken bir class birçok interfacei devralabilir. Bir tane class olacak şekilde, hem class hem de birden çok interfacei aynı anda uygulayabilir.

class A{....}
interface I {....}
interface IB {....}

class B : A, IA, IB {.....} 

Yukardaki B classı derlenecektir. Aynı anda hem bir tane class hem de birden çok interfacei uygulamak mümkündür.

Bununla birlikte interfaceler arasında da bir kalıtım hiyerarşisi oluşturmak da mümkündür.

Aşağıdaki örneği inceleyelim:

interface IA {
        void MethodA();
    }

    interface IB : IA {
        //Burada void MethodA()'yı tanımlamak gerekmez.
        void MethodB();
    }

    class A : IB {
        public void MethodA() { } //IA'dan gelen
        public void MethodB() { } //IB'den gelen
    }

Yukardaki örnekte, A sınıfı IB interfaceinden türemiştir, IB de IA interfaceinden türemişti. Dolayısıyla A sınıfı IA'dan gelen MethodA() ve IB'den gelen MethodB()'yi uygulamak zorundadır.

interfaceler sadece metot tanımlamaz. Aynı zamanda bir properties de tanımlayabilir. Fakat tahmin edileceği üzere get ve set belirteçleri belli bir değer gösteremez.

interfacede bir properties aşağıdaki gibi tanımlanmalıdır:

interface IA {
        int MyProperties { get; set; }
    }



Açık Uygulamalar

Bazen bir interface i uygularken bazı üyelerin private kalmasını isteyebiliriz. Bu durumda interface tanımındaki üye adıinterface adı ile birlikte tanımlayabiliriz. Üyenin bu şekilde açık olarak uygulanmasına neden olur (explicit interface member implementation). Bu tanıma bir örnek aşağıdaki gibidir:

interface IA {
        int MethodA(int i);
    }

 class A : IA {
        int IA.MethodA(int i) { //Bu kısmın private olabileceğine dikkat edin. public de olabilir
            return i / 2;
        }
    }

Daha ilginç bir örnek aşağıdaki gibidir.

  interface IEven {
        bool IsOdd(int x); //Tek mi?
        bool IsEven(int x); //Çift mi?
    }

    class MyClass : IEven {

        bool IEven.IsOdd(int x) { //private olduğuna ve tanım şekline dikkat ediniz (interface adı ile birlikte)
            if ((x % 2) != 0) return true;
            return false;
        }

        public bool IsEven(int x) { //Burası normal tanımlama
            IEven e = this;
            return !e.IsOdd(x);
        }
    }

static void Main(string[] args)
        {
            MyClass ob = new MyClass();

            bool res;
            res = ob.IsEven(4);
            if (res) Console.WriteLine("4 çift sayıdır");

            //res = ob.IsOdd(3); //Hata!! IsOdd() private. erişilemez!

            //Yalnız aşağıdaki kod doğrudur ve derlenecektir. IsOdd() metoduna IEven türünden bir referans ile erişilebilir.
            IEven ieven = (IEven)ob;
            res = ieven.IsOdd(3);
            if (res) Console.WriteLine("3 tek sayıdır");

        }

Bu programın çıktısı tahmin edileceği gibi aşağıdaki gibidir:

4 çift sayıdır
3 tek sayıdır

Yukarda gerekli açıklamaları yaptığım için ayrıca açıklama yapmaya gerek görmüyorum şimdilik.

interfacelerin referans olarak kullanımı, bağımlılıkların kaldırılması kapsamında yaygın bir kullanımı vardır. (IoC, Dependency Injection.. gibi) Fakat bunu daha sonra ele alacağız.

interface konusunu şimdilik burda noktalıyoruz.

Bir sonraki makalede buluşuncaya dek hoşçakalın, sağlıcaklakalın...




Paylaş:

20 Kasım 2017 Pazartesi

C#'ta Kalıtım (Inheritance) - Kalıtımda Sanal Metotlar, Overriding ve Bazı Hususlar - Part 4

Merhaba,

Bir önceki yazıda Kalıtımda Yapılandırıcılar ve Ad Gizlemeden bahsetmiştik. Bu yazıda ise kalıtımda metotlara daha yakından bir bakış atacağız.

Bir sınıf, başka bir sınıfın üyelerini miras alabildiği gibi public metotları da miras alabilir. Fakat bazı durumlarda bu metotların türetilmiş sınıfa ait specific özellikler yerine getirmesi istenebilir. Bu durumda metot adını değiştirip yeni bir metot yazmak mantıklı gelse de, OOP açısından zayıf bir yöntem olacaktır. Bunun yerine temel sınıftan alınan bir metodu özelleştirmek için temel sınıfta sanal metot (virtual) tanımlayıp türetilmiş sınıfta bu metodu devre dışı bırakmak (overriding) gerekir. Bu durumda artık temel sınıftan kalıtım ile gelen metot devre dışı kalacak olup türetilmiş sınıftaki metot geçerli olacaktır. OOP'un çok biçimlilik (polymorphism) özelliği bunu gerektirir. OOP'un nimetlerinden mümkün olduğunca yararlanmak, boyutu büyüyen projeler için daha sağlıklı olacaktır.

Aşağıdaki örneği inceleyelim:

class A
    {
        public virtual void MyVirtualMethod() {
            Console.WriteLine("Bu temel sınıfın sanal metodu");
        }
    }
    
    class B : A {
        public override void MyVirtualMethod()
        {
            Console.WriteLine("Bu da B'nin override ettiği metod");
        }
    }
static void Main(string[] args)
        {
            A a = new A();
            a.MyVirtualMethod();
            B b = new B();
            b.MyVirtualMethod();
}

Bu programın çıktısı aşağıdaki gibi olur:

Bu temel sınıfın sanal metodu
Bu da B'nin override ettiği metod

Öncelikle; A'da bir sanal metot (public virtual) tanımlandığına dikkat edin. Bu metot A sınıfında belli bir işi yerine getirmekte. Fakat B, ekstra işler daha yapmak istemektedir. Bu durumda A'nın metodunu devre dışı bırakıp (public override) kendi işini yapabilmektedir. Eğer; B sınıfı A sınıfındaki metodun da yaptığı işleri yapmak isterse ama ayrıca kendi işini de ilave etmek isterse yine A'daki metodu base anahtar sözcüğü ile çağırabilir. Yukarda B'nin içindeki metot aşağıdaki gibi olabilir:

 class B : A
    {
        public override void MyVirtualMethod()
        {
            base.MyVirtualMethod();
            Console.WriteLine("Bu da B'nin override ettiği metod");
        }
    }

Bu durumda, A'nın metodunun yaptığı işlere ilaveten kendi işlerini de yapabilecektir.

Sanal metotların devre dışı bırakılma gibi bir zorunluluğu yoktur. Devre dışı bırakılmazsa temel sınıftan olduğu gibi devralınabilir.

Sanal metotlar çok yerde işe yarar. Bunun için güzel örneklerden biri de; iki boyutlu şekil sınıfından türeyen üçgen, kare ve dikdörtgen sınıflarının kendi AlanHesapla() metotlarının olabilmesidir. Her geometrik şeklin alan hesaplaması farklı olacağından her bir alt sınıf bu metodu override ederek uygulayacaktır.

Ufak bir not: sanal metotlar public olmak zorundadır. private, abstract ya da static olamazlar. 


Kalıtıma Dair Diğer Hususlar

Daha önce abstract classlar ve metotlardan bu linkte bahsetmiştik. Detaylar için bu linke bakabilirsiniz. Kısaca bahsetmek gerekirse; abstract classlar mutlaka kalıtım yoluyla aktarılabilen özet classlardır. abstract classlar bir nevi yarım classlardır tam bir iş tanımlamamaktadır. Dolayısıyla new anahtar sözcüğüyle oluşturulamazlar. Bir işi yapabilen metotlara sahip olabilmekle birlikte, abstract metotlara da sahip olabilmektedir. Abstract metotlar, abstract classları devralan sınıflarda mutlaka uygulanmak zorundadır.

abstract classlar mutlaka kalıtım ile kullanılabilmelerine karşın, kalıtımı önleyen sealed yapısı da mevcuttur. Bir sınıf neden kalıtım ile aktarılamasın ki buna ne gerek var diye düşünebilirsiniz. Bazı özel durumlarda bu işe yarar. Örneğin; tıbbi, elektronik vb gibi bir cihazınızın ilk kullanıma hazırlanmasını ayarlayan bir sınıfınız olsun. Böylece bunu kullanan kullanıcıların bu ilk hazırlanma şeklini değiştirebilmelerini istemeyebilirsiniz. Bu durumda sealed yapısını kullanmak işinizi görecektir.

sealed class A {........}

class B : A {......} //Hata!!! A sınıfından sınıf türetemezsiniz.


Bu yazıda kalıtım konusunu noktalıyorum.

Faydalı olabildiysem ne mutlu bana.. Anlaşılmayan bir şey olursa yorum kısmına yazabilirsiniz. Dilim döndüğünce anlatmaya çalışırım.

Bir sonraki yazıda buluşuncaya dek sağlıcaklakalın...
Paylaş:

19 Kasım 2017 Pazar

C#'ta Kalıtım (Inheritance) - Kalıtımda Yapılandırıcılar ve Ad Gizleme - Part 3

Merhaba,

Bir önceki yazıda kalıtımda üye erişimi konusunu ele almıştık. Bu yazıda ise kalıtımda yapılandırıcılardan ve ardından ad gizleme kavramından bahsedeceğim.

Bildiğiniz üzere her sınıfın bir yapılandırıcısı vardır. Siz tanımlamasanız bile default bir yapılandırıcı vardır. Bir kalıtım hiyerarşisinde hem temel sınıf hem de türetilmiş sınıfların kendi yapılandırıcılarını çağırmaları mümkündür. Peki bu durumda türetilmiş sınıf hangi yapılandırıcıyı çağıracak gibi bir soru akla gelebilir ki gelmelidir. Cevap: her iki sınıf da kendi yapılandırısını çağırır. Bu akla yatkındır çünkü temel sınıf, türetilmiş sınıfın ne yaptığından habersizdir ve kendi işini kendisi görecektir.

Aşağıdaki örnek bunu ifade eder:

 class A
    {
        public A() {
            Console.WriteLine("Bu temel sınıfın yapılandırıcısı");
        }
    }
    class B : A {
        public B() {
            Console.WriteLine("Bu da türetilmiş sınıfın yapılandırıcısı");
        }
    }
static void Main(string[] args)
        {
            B b = new B();
        }

Bu programın çıktısı, tahmin edeceğiniz üzere aşağıdaki gibi olur (çıktı sırasına dikkat ediniz. önce temel sınıfın yapılandırıcısı çağrılmakta):

Bu temel sınıfın yapılandırıcısı
Bu da türetilmiş sınıfın yapılandırıcısı

Peki kalıtım hiyerarşisi daha çok seviyeli olduğu zaman ne olur? Örneğin; class C : B {} olursa? Bu durumda da yine en tepedeki hiyerarşiden başlayarak aşağı doğru yapılandırıcılar çağrılır.

Yukardaki örneğe ekleme yapalım.

 class A{
        public A() {
            Console.WriteLine("A'nın yapılandırıcısı");
        }
    }

    class B : A {
        public B() {
            Console.WriteLine("B'nin yapılandırıcısı");
        }
    }

    class C : B {
        public C() {
            Console.WriteLine("C'nin yapılandırıcısı");
        }
    }

static void Main(string[] args){
            C c = new C();
}

Tahmin edeceğiniz üzere çıktı aşağıdaki gibi olur:

A'nın yapılandırıcısı
B'nin yapılandırıcısı
C'nin yapılandırıcısı


Peki daha karmaşık yapılandırcılarımızın olduğunu varsayalım. Bu durumda türetilmiş sınıf, temel sınıfın yapılandırıcısını çağırabilir. Zaten OOP'un kurallarından biri de mümkün mertebe bir kodu bir yerde yazmak ve defalarca çağırabilmek, dolayısıyla hataları mimimuma indirgemektir. Türetilmiş sınıf, temel sınıfın yapılandırıcısını çağırırsa temel sınıfın yaptığı ekstra işlerden kurtulmuş olur. Ancak türetilmiş sınıf kendine özgü işleri yerine getirecekse, bunu ayrıca deklare etmelidir. Peki temel sınıfın yapılandırıcısını nasıl çağıracağız? Bunu base anahtar sözcüğü ile halledeceğiz. Daha fazla laf kalabalığı yapmadan sözü aşağıdaki örneğe bırakalım:

    class IkiBoyutluSekil
    {
        public IkiBoyutluSekil(double _genislik, double _yukseklik) {
            this.Genislik = _genislik;
            this.Yukseklik = _yukseklik;
        }

        double genislik;
        double yukseklik;

        public double Genislik
        {
            get { return genislik; }
            set { genislik = value; }
        }
        public double Yukseklik
        {
            get { return yukseklik; }
            set { yukseklik = value; }
        }
    }

    class Ucgen : IkiBoyutluSekil {

        string isim;
        public string Isim
        {
            get { return isim; }
            set { isim = value; }
        }

        public Ucgen(double _genislik, double _yukseklik, string _isim) : base(_genislik, _yukseklik) {
            this.Isim = _isim;
        }

        public double Alan() {
            return Genislik * Yukseklik / 2;
        }     
    } 

static void Main(string[] args)
        {
            Ucgen ucgen = new Ucgen(10, 20, "üçgen");
            Console.WriteLine("Şeklin adı: " + ucgen.Isim);
            Console.WriteLine("Şeklin alanı: " + ucgen.Alan());
        }

Bu kodun çıktısı aşağıdaki gibi olacaktır:

Şeklin adı: üçgen
Şeklin alanı: 100

Bu kodu incelemek gerekirse; Ucgen sınıfı IkiBoyutluSekil sınıfından türemiştir (class Ucgen : IkiBoyutluSekil {....}). IkiBoyutluSekil temel sınıf olup kendi yapılandırıcısına sahiptir. Ucgen sınıfı ise IkiBoyutluSekil sınıfının yapılandırıcısını kullanmaktadır. Burada base anahtar sözcüğüne, konumuna ve kullanım şekline dikkat ediniz. IkiBoyutluSekil sınıfı Genislik ve Yukseklik propertieslerine ilk değer ataması yapıyor. Ucgen sınıfı ise base(_genislik, _yukseklik) ile temel sınıfın yapılandırıcısını çağırarak tekrar tekrar ilk değer ataması yapmıyor. Zaten IkiBoyutluSekil sınıfı bunu yapıyordu. Böylece Ucgen sınıfı bu yükten kurtulmuş oldu.

Bir başka konuya değinmek gerekirse;

Kalıtımda Ad Gizleme

Kalıtım hiyerarşisinde temel sınıf ile aynı ada sahip değişkenler tanımlamak mümkündür. Bu durumda temel sınıftaki değişken gizlenmiş olup, türetilmiş sınıftaki değişken geçerli olacaktır. Ad gizleme işlemini yapmak istediğimiz değişkenin başına new anahtar sözcüğünü eklemeliyiz.

Aşağıdaki basit örnek ad gizleme kavramını anlatmaktadır.

  class A
    {    
        public int x = 10;
    }

    class B : A {

        new int x = 11; //A'daki x'i gizledik

        public B() {
            Console.WriteLine(x);
        }
    }

B b = new B(); dediğimizde çıktımız "11" olacaktır. Tanımlara dikkat ediniz.

Bu işlemin tam tersi de mümkündür. Bir değişken türetilmiş sınıfta gizlenebildiği gibi, temel sınıf içindeki değişken de açığa çıkarılabilir. Bunun için base anahtar sözcüğünü kullanacağız.

Aşağıdaki örneği inceleyelim:

class A
    {    
        public int x = 10;
    }

    class B : A {

        new int x = 11;

        public B() {

            int a = base.x; //bu A'nın içindeki x
            int b = x; //bu B'nın içindeki x

            Console.WriteLine("A'nın içindeki x: " + a);
            Console.WriteLine("B'nın içindeki x: " + b);
        }
    }


B b = new B(); dediğimizde çıktımız

A'nın içindeki x: 10
B'nın içindeki x: 11

olacaktır. base'in kullanımına dikkat ediniz.

Bu yazıyı şimdilik burda noktalıyoruz. Anlaşılmayan bir konu varsa yorumlar kısmında yazabilirsiniz.

Bir sonraki yazıda Kalıtımda Overriding konusunu ele alacağız.

Bir sonraki yazıda buluşuncaya dek sağlıcaklakalın...

Paylaş:

17 Kasım 2017 Cuma

C#'ta Kalıtım (Inheritance) - Kalıtımda Üye Erişimi - Part 2

Merhaba,

Bir önceki makalemizde kalıtıma giriş yapmıştık. Bu makalede ise üye erişimi konusunu inceleyeceğiz.

Bildiğiniz üzere OOP mimarisinde bir sınıfın private üyelerine dışardan erişim söz konusu değildir. Bu kural kalıtımda da geçerlidir. Yani bir A sınıfı, B sınıfını kalıtım yoluyla devraldığı zaman B'nin private üyelerine erişemez. Bu ilk bakışta ciddi bir kısıt gibi gözükebilir ama private üyelere dolayı yollardan erişim sağlanabilir. Örneğin; propertiesler sayesinde dolaylı erişim sağlanabilir.

 class A{
        private int x;
        public int X
        {
            get { return x; }
            set { x = value; }
        }
    }

    class B : A {   }

     static void Main(string[] args) {
            B b = new B();
            b.x = 10; //Hata!! private üyeye erişim yok
            b.X = 10; //Hata yok. public üye            
        }

Peki bazı özel durumlarda temel sınıfın private üyesine erişmemiz gerektiği durumda ne yapacağız? Üyeyi public hale getirirsek bu üyeye dışardan her türlü erişim mümkün olabilecek. Merak etmeyin, dil mühendisleri buna da çare bulmuşlar: protected üye. protected üyeler yalnızca kalıtım yoluyla aktarılan sınıflarca erişilebilmektedir. Dışardan erişim yine sözkonusu değildir. protected üye, türetilmiş sınıf için public özelliği gösterir. Fakat dışardan erişimler için yine privatedir.

Aşağıdaki örneği inceleyelim:

 class A{
        protected int x;
    }

    class B : A {
        public B(int _x) {
            this.x = _x; //Buraya dikkat! this.x ifadesi A'daki protected int x değişkenidir
            Console.WriteLine(x.ToString());
        }
    }

 static void Main(string[] args){
            A a = new A();
            a.x = 10;//Hata!! protected üyeye erişim yok
            
            B b = new B(10); //B classına göz atın
        }

Yukardaki örneği incelersek; A sınıfından bir nesne oluşturduğumuz zaman (A a = new A()) pretected int x; üyesine dışardan erişim sağlayamayız ama A'yı devralan B sınıfı this.x ile A'nın protected üyesine erişim sağlayabilmektedir. Bu kısma dikkat etmelisiniz.

Kalıtımda üye erişimiyle ilgili kısa bir bilgi vermiş olduk. Bir sonraki makalemizde Kalıtımda Yapılandırıcılar ve Ad Gizleme konusunu ele alacağız.

Sağlıcaklakalın...
Paylaş:

14 Kasım 2017 Salı

C#'ta Kalıtım (Inheritance) - Kalıtıma Giriş - Part 1

Merhaba,

Bu yazı dizimde sizlere Object Oriented Programming'in en güçlü özelliklerinden biri olan Kalıtım(Inheritance)'ı anlatmaya çalışacağım. Bu yazıdan itibaren sırayla 4 part şeklinde anlatmaya çalıştım. Part 1'imize giriş yaparak başlayalım.

Bildiğiniz üzere OOP'un 3 temel prensibi vardır.
  1. Sarmalama (Encapsulation) (daha sonra detaylı olarak anlatacağım)
  2. Çok Biçimlilik (Polymorphism) (daha sonra detaylı olarak anlatacağım)
  3. Kalıtım (Inheritance)
OOP mimarisinde hedeflenen şeylerden birisi de kod tekrarını önlemektir. Bir kodu bir yerde yazıp defalarca kez her yerde kullanabilmektir. Kalıtım bu amaca da hizmet etmektedir. Dolayısıyla kalıtım, C# olsun Java olsun OOP mimarisinin çok güçlü bir özelliğidir. Kalıtım herkesin bildiği üzere bir sınıfın özelliklerini devralabilme özelliğidir. Bu çok önemlidir. Aynı zamanda hiyerarşik bir yapı oluşturmamızı da sağlar. Örneğin elma, meyve sınıfının bir örneğidir ve meyve sınıfının bütün özelliklerini taşır ama aynı zamanda kendine özgü özellikleri vardır.

Kalıtım yoluyla özellikleri alınan sınıfa temel sınıf, özellikleri devralan sınıfa da türetilmiş sınıf denir. Bu yazı dizisinde bu kavramları sık sık kullanacağım.

Hemen bir örnekle başlayalım. İki boyutlu şekilleri ifade eden bir sınıfımız olsun. Bu sınıftan üçgen sınıfı türetelim.

using System;

namespace Kalitim
{
    class IkiBoyutluSekil
    {
        public double Genislik;
        public double Yukseklik;

        public void BoyutGoster() {
            Console.WriteLine("Genişlik: " + Genislik + " Yükseklik: " + Yukseklik);
        }
    }

    class Ucgen : IkiBoyutluSekil {
        public double Alan() {
            return Genislik * Yukseklik / 2;
        }
        public void AlanGoster() {
            Console.WriteLine("Üçgenin Alanı: " + Alan().ToString());
        }
    }

    static void Main(string[] args)
    {
        Ucgen ucgen = new Ucgen();
        ucgen.Genislik = 10;
        ucgen.Yukseklik = 20;
        ucgen.BoyutGoster();
        ucgen.AlanGoster();
        Console.Read();
    }
}

Bu programın çıktısı aşağıdaki gibi olacaktır:

Genişlik: 10 Yükseklik: 20
Üçgenin Alanı: 100

Dikkat edilirse Ucgen sınıfı Genislik, Yukseklik alanlarını ve BoyutGoster() metodunu temel sınıftan (IkiBoyutluSekil sınıfı) kalıtım yoluyla devralmıştır. Ayrıca Ucgen sınıfında bu kodların yazılmasına gerek yoktur. Bununla birlikte IkiBoyutluSekil sınıfının Ucgen sınıfından hiçbir şekilde haberi yoktur. Kalıtımın en temel hali bu şekildedir.

Önemli Not: C++ ile kod yazanlar bilir ki, bir sınıf birden çok sınıf özelliklerini kalıtım yoluyla devralabiliyordu. Fakat C#'ta bir sınıf yalnızca tek bir sınıftan türeyebilir. Yani aşağıdaki gibi bir ifade C# için hatalıdır.

class A {}
class B{}
class C : A, B {} //Hata!!! Birden çok sınıf miras alınamaz!

Bunun nedeni şudur: Diyelim ki, A ve B sınıfları da X sınıfından türemiş olsun. A ve B sınıfları X sınıfındaki herhangi bir metodu override ettiğinde C sınıfı hangi sınıfın override metoduna sahip olacak, A'nın mı B'nin mi? gibi problemler olmasın diye bu şekilde çoklu kalıtıma izin verilmemiş. Peki C++'ta bu nasıl çözülüyordu? Bunun detaylarına şimdi girmek istemiyorum ama çeşitli çözümler tabi ki getirilmişti ama bundan neden vazgeçildi diye sorulursa; casting, reflection gibi konularda fazlaca karışıklık getirmesinden çekinilmiştir. Zaten çoklu kalıtımı interfacelerle istediğimiz gibi yönetebiliyoruz hem de çok daha basit halde.

Bunun tersi ise geçerlidir. Yani A sınıfından B ve C sınıfları türeyebilir.

class B : A {} ve class C : A {} ifadeleri geçerlidir.

Bir sınıf birden fazla sınıfı kalıtım yoluyla devralamaz demiştik fakat birden fazla interface'i uygulayabilir. Bunu ilerleyen derslerde ele alacağız.

Kalıtımda türetilmiş sınıf, temel sınıfın bütün public özelliklerini devralabilir. Fakat private özelliklerini devralamaz. Bunun için farklı mekanizmalar geliştirilmiştir.

Bu yazımızda kısaca kalıtım konusuna giriş yaptık. Bir sonraki yazımızda "Kalıtımda Üye Erişimi" konusunu ele alacağız.

Sağlıcaklakalın...


Paylaş:

2 Kasım 2017 Perşembe

C# Abstract Classlar (Özet Sınıflar) ve Abstract Metotlar (Özet Metotlar)


Merhaba, bu yazıda abstract yapısı ve interface ile arasındaki farkları inceleyeceğiz.

Abstract yapısı kalıtım mimarisinde önemli bir yere sahiptir. Abstract, özet demektir. Abstract classlar ancak kalıtım yoluyla devralınabilirler, new sözcüğü ile oluşturulamazlar. Çünkü barındırdığı abstract metotlar herhangi bir işi yerine getirmemektedir. Sadece metot prototipini tanımlamaktadır. Tanımlanan bu abstract metotların içinin boş olduğundan yola çıkarak abstract classların new sözcüğü ile oluştutulmaması gerektiği anlaşılabilir. Ayrıca abstract classtaki bütün abstract metotlar devralan nesne tarafından uygulanmak zorundadır. Aksi takdirde hata verecektir.

Anlamanız açısından şöyle bir örnekle başlayalım: TwoDimensionalShape adında iki boyutlu şekilleri ifade eden bir nesnemiz olsun.  Bu nesneyi kalıtım yoluyla devralan dikdörtgen, üçgen.. vs gibi şekil nesneleri olsun. Her şeklin mutlaka bir Alan hesaplaması isteniyor olsun. Bu durumda Area() metodunu abstract olarak tanımlarsak devralan classta bu metodu tanımlama zorunluluğu olacak. Her bir şeklin alan hesaplaması farklı olacağından her şekil nesnesi kendi Area() metodunu uygulayacak.

Abstract classların bütün metotları abstract olmak zorunda değildir, aynı zamanda işlevi olan metotlar da barındırabilirler ama abstract metodu olan bir class, abstract olmak zorundadır.

Yukardaki örneği kodlarla anlatan aşağıdaki örneği inceleyelim.

using System; namespace AbstractOrnek { public abstract class TwoDimensionShape { int width, heigth; string name; public int Width { get { return width; } set { width = value; } } public int Heigth { get { return heigth; } set { heigth = value; } } public string Name { get { return name; } set { name = value; } } public TwoDimensionShape(int width, int heigth, string name) { this.Width = width; this.Heigth = heigth; this.Name = name; } public abstract double Area(); public string NotAbstractMethod() { return "Bu bir abstract metot değildir"; } } //Dikdörtgen public class RectangleShape : TwoDimensionShape { public RectangleShape(int width, int heigth, string name) : base(width, heigth, name) { } public override double Area() { return Width * Heigth; } } //Üçgen public class TriangleShape : TwoDimensionShape { public TriangleShape(int width, int heigth, string name) : base(width, heigth, name) { } public override double Area() { return Width * Heigth / 2; } } class Program { static void Main(string[] args) { RectangleShape rectangleShape = new RectangleShape(10, 20, "Dikdörtgen"); Console.WriteLine("Dikdörtgenin alanı: " + rectangleShape.Area()); TriangleShape triangleShape = new TriangleShape(10, 20, "Üçgen"); Console.WriteLine("Üçgenin alanı: " + triangleShape.Area()); Console.WriteLine(triangleShape.NotAbstractMethod()); Console.ReadLine(); } } }

Bu programın çıktısı şu şekilde olacaktır:

Dikdörtgenin alanı: 200
Üçgenin alanı: 100
Bu bir abstract metot değildir

Görüldüğü üzere her şekil kendi Area() metodunu zorunlu olarak uygulamaktadır.

abstract ile interface arasındaki temel fark ise, abstract classlarda herhangi bir işi yapabilen metotlar bulunabiliyorken interface'de bütün metotların içi tamamen boş olmalıdır. interface temelde bir işin nasıl yapılacağını değil de hangi işlerin yapılacağını tanımlar.

Anlaşılmayan bir şey varsa bu yazının altına yorum olarak yazabilirsiniz.

Sağlıcaklakalın...

Paylaş:

C# Struct ile Class Arasındaki Farklar


Merhaba, bu yazıda birçok programcının aklına gelen bir konu hakkında kısaca bilgi vermek istiyorum. struct ile class arasında ne gibi farklar var?

C ile kod yazan arkadaşlar struct ile ilk tanıştıklarında ne kadar güzel bişey olduğunu farketmişlerdir. Hatta uzun süre struct ı kullanıp OOP'a geçenler class lara alışmakta biraz zorlanmışlardır.

Temelde classlar structların yapabildiği herşeyi yapabilmekte. Peki aradaki temel fark nedir? Bu sorunun cevabı OOP mimarisinde yatmaktadır. struct ile classların arasındaki en büyük fark (OOP'un en güçlü özelliği) kalıtımdır. structlar kalıtımı desteklememektedir. Bu sorunun kısaca cevabı budur. Bu cevaptan sonra diyebilirsiniz ki classlar structların bütün özelliklerini yerine getirebiliyorlarsa o zaman C#'ta structlar neden var derseniz, structlar daha performanslıdır. Yüksek performas gerektiren bazı özel durumlarda class yerine struct tercih edilebilir. Böylece classların referans özelliğinden kaynaklı ek işlemlerin olmamasıyla performans artacaktır.

Umarım faydalı olmuştur.

İyi çalışmalar dilerim...
Paylaş:

Bu Blogda Ara