.NET 4.0’da Varyans (Kovaryans ve Kontravaryans) Kavramı

Merhaba; yenilikleri hızlıca kavrayıp bir an önce uygulayan yazılımcı dostlarım. Bu yazımda yine, bir çok kaynakta .net 4.0 yeniliği olarak geçen fakat, anlaşılması pek de kolay olmayan konudan bahsedeceğim: Varyans.

Önce dilerseniz, varyansın (ingilizce: variance) ne olduğuna biraz değinelim. Yo vazgeçtim fazla değinelim (neden azla yetinelim ki). Efendim fark ettiğiniz üzere ben yine ilk paragraftaki ciddi duruşumu şu an kaybettim. Uzatmayayım en iyisi. Ne diyorduk? Varyansın ne olduğundan bahsediyorduk. Varyans kelimesini ilk duyduğumda, yanlış hatırlamıyorsam lisede matematik dersinde permütasyon, kombinasyon ve olasılık konusunda karşılaştığımız bir kavram olduğunu sandım. Belki, sizlerden bazıları da aynı sanrıyı yaşamıştır. Ancak rahatlayın çünkü bu varyansın o varyans ile hiç bir ilgisi yok. Buradaki varyans, genetik varyans (meraklısına). Çok basite indirgersek anlamı şu: Bir canlının, mutasyona uğrayarak başka bir canlı türüne dönüşmesine (kontravaryans) ya da geriye bir üstteki akrabasına dönüşmesine (kovaryans) verilen isim. Aslında bu tanım, kod mimarisindeki tanımı da içinde saklıyor. Bir nesne, kendini türeten nesneye atandığına (kovaryans) ya da tersi olduğunda (kontravaryans) varyanstan bahsetmek mümkün. Peki türetilmiş nesneler ile türeten nesneleri iki farklı koleksiyonda tutsak, bu koleksiyonlar da birbirlerine dönüşebilirler mi?

Tamam tamam asmayın suratınızı! Örnek geliyor; Elma sınıfı, Meyve sınıfından türüyorsa, Elma sepeti de Meyve sepetinden türemiş olur mu diye soruyorum 🙂

Tahmin edersiniz ki varyans dediğimiz kavramın .net 4.0 ile gelen (daha önce olmayan) bir şey olduğunu söylemek yanlış olur. Çünkü, hiç duymamış veya üzerine eğilmemiş olsak da, nesne yönelimli programlama yapısına uygun tüm dillerde var olan bir olgu bu. Öyleyse; .net 4.0’da varyans ‘düzeltilmiştir’ demek sanki daha doğru olur. Peki sorunlar neydi ve düzeltmek için nasıl bir yol izlendi? Gelin bu serüvene bir göz atalım.

Önce; tüm örneklerde kullanacağım sınıflarımı oluşturayım:

.NET 1.1. Sorun: Kontravaryans mı? O da ne?

 

Sorun; başlıktandan anlaşıldığı gibi, .net 1.1’de kontravaryans diye bir şeyin varlığı bile söz konusu değildi. Varyans, bu versiyonda sadece kovaryans olarak karşımıza çıkıyordu. Yukarıda yaptığımız tanıma bakarsak (Elma ve Meyve) varyansı en net kullandığımız alanlar, diziler ve koleksiyonlar. O zaman örneğimizi dizi üzerinden devam ettirelim.

Herhalde böyle bir kod yazsam kimse tuhaf bulmayacaktır. Gördüğünüz gibi Gitar dizisinin içerisine, kendisinden miras alan “ElektroGitar” tipinde bir nesne atıyorum. Sorun yok elbette. Burada dizinin kovaryans olduğunu söyleyebilirim. Ama şimdi biraz saçmalayalım. Bakalım ne tepki verecek:

Evet oldukça mantıksız. ElektroGitar’ların arasında sadece ElektroGitar olmalı ama ben Gitar eklemeye çalışıyorum. Bu noktada build ettiğinizde hata almıyorsunuz. Ama kodu çalıştıracak olursanız:

 

.NET 2.0: Generic geldi, hoş geldi.

 

İşte çalışma zamanında (run-time) meydana gelen bir hata! Hem de tip nedeniyle oluşan bir hata! İşte bu hatalardan kurtulmanın yolu .NET 2.0 ile geldi. Dediler ki, belirli bir tipte bu işleri yapacaksanız Generic tipleri kullanın. Ama generic tiplerde varyans hiçbir şekilde uygulanamaz! Bu durumda generic tipler invaryant’dır diyebiliriz.

Gördüğünüz gibi siz kodunuzu yazar yazmaz “bu olmaz abi” diyerek altını çiziverdi. En azından run-time hatasını önlemiş olduk. Herşey yolunda gözüküyor değil mi? Durun bir saniye! Bir elektrogitar koleksiyonu aynı zamanda bir gitar koleksiyonu mu peki?

Yani:

İşte problem! İki Generic interface arasında kovaryans’tan bahsetmek mümkün görünmüyor!

.NET 4.0’ın IN’leri ve OUT’ları

 

Fakat şimdi, yani .net 4.0’da yukarıdaki kodun aynısını yazdığınızda artık hata almayacaksınız. Söz konusu türetilen nesne koleksiyonu, temel nesne koleksiyonuna atanabiliyor. Peki tamam ama neden hata almıyorum 4.0’da?

Çünkü; .NET 4.0’da Generic Interface (ya da delege) yazarken, belirttiğiniz tipe bir parametre ekleyerek varyans uygulanıp uygulanamayacağını belirtebiliyoruz. Bu parametreler; OUT ve IN. Out parametresi, kovaryans yapılabileceğini, In ise kontravryans durumuna uygun olacağını belirtiyor (Hemen bir ipucu: out, bu sınıfı miras alanlar, bu tipe atanabilir – dönüşüm. In: bu sınıfa miras veren tipler, için de geçerlidir). Bu durumda; yukarıdaki kodda kullandığım IEnumarable interface’i out parametresi içeriyor. Görelim:

Bakın açıklamada ne diyor: This type parameter is covariant.Gayet açıklayıcı aslında değil mi?

Peki şimdi kontravaryans ile ilgili bir örnek yapalım dilerseniz.

Bunun için, Gitar ve Elektrogitar sınıflarımı biraz değiştiriyorum:

Şimdi, bu iki sınıftan türeyen iki farklı nesnenin birbirleriyle karşılaştırılabilir olmasını istiyorum. Bunu yapmak için ayrı bir sınıf tanımlıyorum:

Burada sınıfımızın, IComparer<in T> interface’ini içerdiğini görüyoruz. İşte burada da “in” parametresi var. Yani, FiyatKarsilastirici sınıfımız, kontravaryans’a uygun bir yapı olacak.

O zaman testimizi yapalım.

Bu kod, gayet beklediğiniz gibi değil mi? Sonuçta, FiyatKarsilastirici nesnemiz, Gitar nesnesini karşılaştırmak için yazılmıştı. Fakat, Gitar nesnesi yerine ElektronikGitar nesnesi de verebiliyor olmam gerek değil mi? İşte bunu yapabilmem demek, kontravaryans uyguluyor olmam demek.

İşte yukarıda görmüş olduğunuz kod, .net 4.0 öncesinde kesinlikle çalışamazdı. O zaman hep birlikte; “hoş geldin kontravans” diyebiliriz!

Sevgili dostlarım; biliyorum varyans kavramını anlamak çok kolay değil. Elimden geldiğince basitleştirmeye çalıştım. Sadece şunu söyleyebilirim; minik gibi görünen bu değişiklikler, aslında mimari açıdan çok büyük atılımlara yol açıyor. Benim aklıma ilk gelen mimari değişiklik; observer design pattern’de daha estetik kod yazılabileceği mesela.

Eh efendim, bunu denemek de artık size kalmış. Benden bu kadar. Bir sonraki makalede görüşmek dileğiyle hoşçakalın.

7 thoughts on “.NET 4.0’da Varyans (Kovaryans ve Kontravaryans) Kavramı

  1. net 4.0’da gelen in ve out parametrelerini anlayamamıştım ama sizin yazınızdan sonra herşey masmavi bir gökyüzü gibi açık. son derece pedagojik bir yazı yazmışsınız. devamını da bekler, teşekkür ederiz.

  2. Makale süper olmuş hocam klavyenize sağlık örneklemeler dahada süper olmuş anlaşılabilitesi yüksek 🙂

  3. Türkay hocam enfes bir anlatım yine. Bir kaç gündür blog sayfanız kapalıydı tekrar açıldığına sevindim ayrıca makalelerinizi daha sık bekliyoruz 🙂

Leave a Reply