ÖĞRENME FAALİYETİ 1 ÖĞRENME FAALİYETİ 1

Benzer belgeler
BİLİŞİM TEKNOLOJİLERİ

abstract Sınıflar 1 Sınıf sınıf1 new class Ama aşağıdaki şekilde referans alınabilir;

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

public static int Toplam int x, int y

NESNEYE YÖNELİK PROGRAMLAMA

Ders 8 Konu Özeti ve Problemler

Lambda İfadeleri (Lambda Expressions)

BĠLĠġĠM TEKNOLOJĠLERĠ

Önemli noktalar. Paradigma Nesnelere Giriş Mesajlar / Ara bağlantılar Bilgi Gizleme (Information Hiding ) Sınıflar(Classes) Kalıtım/Inheritance

Java da Soyutlama ( Abstraction ) ve Çok-biçimlilik ( Polymorphism )

Nesne Yönelimli Programlama ve Kalıtım

Görsel Programlama DERS 02. Görsel Programlama - Ders02/ 1

Sunum İçeriği. Programlamaya Giriş

BTEP243 Ders 3. class Yazım Kuralı:

5.HAFTA. Sınıf ve Nesne Kavramı, Metot Oluşturma, Kurucu Metot, this Deyimi

BİL-141 Bilgisayar Programlama I (Java)

HSancak Nesne Tabanlı Programlama I Ders Notları

NESNE TABANLI PROGRAMLAMA-1 DERS UYGULAMALARI (22 EYLÜL - 14 KASIM

ANA SINIF TÜRETİLEN BİRİNCİ SINIF TÜRETİLEN İKİNCİ SINIF

YZM 2105 Nesneye Yönelik Programlama

Operator Aşırı Yükleme (Operator OverLoading)

1 C#.NET GELİŞTİRME ORTAMI 1 Visual Studio 2015 Arayüzü 4 Menu Window 6 Solution Explorer 7 Properties Window 8 Server Explorer 8 Toolbox 9

Kalıtım (Inheritance)

C++ Dersi: Nesne Tabanlı Programlama

Sınıflar ve Yapılar Arasındaki Farklılıklar. Değer ve Referans Türde Olan Aktarımlar

Nesne tabanlı programlama nesneleri kullanan programlamayı içerir. Bir nesne farklı olarak tanımlanabilen gerçek dünyadaki bir varlıktır.

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

BİL-142 Bilgisayar Programlama II

C#(Sharp) Programlama Dili

1. SINIFLAR Sınıf (Class) Mantığı

HSancak Nesne Tabanlı Programlama I Ders Notları

HSancak Nesne Tabanlı Programlama I Ders Notları

Ders 8: Metotlar. barisgokce.com

Nesneye Dayalı Programlama

Operatörlerin Aşırı Yüklenmesi

Nesneye Yönelik Programlama (OOP) 7.Hafta

Göstericiler (Pointers)

Nesne Yönelimli Programlama

Arayüz soyut metotların oluşturduğu bir koleksyondur. Bir sınıf arayüzü çalıştırırken arayüzün sahip olduğu soyut metotları da miras alır.

NESNEYE YÖNELİK PROGRAMLAMA

YZM 2105 Nesneye Yönelik Programlama

JAVA PROGRAMLAMA DİLİ ÖZELLİKLERİ

Sınıf Diyagramları Amaç: Sınıf Diyagramları Nasıl Çizilir?

YZM 2105 Nesneye Yönelik Programlama

YZM 2105 Nesneye Yönelik Programlama

Nesneye Dayalı Programlama

Mühendislik Fakültesi Elektrik-Elektronik Mühendisliği C Programlama 7. Bölüm Metot Tanımlama ve Kullanma

PROGRAMLAMAYA GİRİŞ FONKSİYONLAR

Programlama Dilleri 1. Ders 12: Belirleyiciler ve Niteleyiciler

BMH-303 Nesneye Yönelik Programlama

C# Programlama Dili. İlk programımız Tür dönüşümü Yorum ekleme Operatörler

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Diziler İndisli Değişkenler

Yrd. Doç. Dr. Caner ÖZCAN

HSancak Nesne Tabanlı Programlama I Ders Notları

C de Detaylı Üs Alma Programı. C# Dilinde Metot Tanımlama ve Yazdırma

3. NESNE TABANLI PROGRAMLAMANIN PRENSİPLERİ

NESNE TABANLI PROGRAMLAMA Temel Kavramlar

Pointer Kavramı. Veri Yapıları

ALGORİTMA VE PROGRAMLAMA I

C++ Dersi: Nesne Tabanlı Programlama

ALGORİTMA VE PROGRAMLAMA I

ELN1001 BİLGİSAYAR PROGRAMLAMA I

YZM 2105 Nesneye Yönelik Programlama

Genel Programlama II

C# Yazım Kuralları ERCİYES. Ü. BİLGİSAYAR M. COMPUTER PROGRAMMING II 1 FEHİM KÖYLÜ

İsimler ve Kapsam. 24 Şubat Programlama Dilleri - Pamukkale Üniversitesi 1

C Dersleri Bölüm 3 : Program akışı

C Programlama Dilininin Basit Yapıları

NESNEYE YÖNELİK PROGRAMLAMA SINIFLAR

C# nedir,.net Framework nedir?

Nesneye Dayalı Programlama

YAPILAR BİRLİKLER SAYMA SABİTLERİ/KÜMELERİ. 3. Hafta

7. HAFTA. Erişim Belirleyiciler

YZM 2105 Nesneye Yönelik Programlama

İsimler ve Kapsam. Hafta 4 Ders 2 BLG339 PROGRAMLAMA DİLLERİ KAVRAMI

Sınıf üyeleri: değişkenler (fields) and metotlar (methods) Değişkenler: nesne içerisindeki değişkenlerdir Temel veri tipi veya sınıf tipi

Nesne Yönelimli Programlama

Nesne Tabanlı Programlama

/*Aşağıda ki kodları doğru şekilde anlar ve kullanırsanız java da sınıfları biraz da olsa anlamış olursunuz.*/

Bölüm 12. Nesne yönelimli programlama desteği

Yeni bir proje açarken File New - Web Site diyoruz. Gelen ekranda Visual Basic veya C# seçilebilir. Biz ders kapsamında C# programlama dilini seçtik.

Bir dizinin boyutları sabittir ve kullanılmadan önce belirlenmelidir. Dizi boyutunu belirlemek için başka bir değişkende kullanabilirsiniz.

PASCAL PROGRAMLAMA DİLİ YAPISI

Mantıksal İşlemler. 7.1 true, false, nil

Bu parçalar arasındaki ilişkiyi kullanıp büyük çaplı programlar geliştirme tekniğine de nesne yönelimli programlama denir.

Klavyeden Basit Giriş/Çıkış İşlemleri

Bölüm 11. Soyut veri tipleri ve kapsülleme kavramları ISBN

İçerik. Kapsülleme ( Encapsulation ) Java da Kalıtım: Örnek 2.1. Kalıtım ( Inheritance ) Tekrar Ziyaret. Java da Kalıtım: Örnek 2.2.

Statik veri üyeleri sınıf dosyası içerisinde, ancak sınıf bildirimi dışında başlatılmalıdır. Statik üye fonksiyonları

Sınav tarihi : Süre : 60 dak. a) ABCDE b) BCDE c) ABCD d) kod hatalı e) BCD

Arayüz (Interface) Altuğ B. Altıntaş 2003 Java ve Yazılım Tasarımı - Bölüm 7 1

ALGORİTMA VE PROGRAMLAMA I

Yrd. Doç. Dr. Caner ÖZCAN

Nesne Yönelimli Programlama

BMÜ-111 ALGORİTMA VE PROGRAMLAMA AKIŞ KONTROLÜ YRD. DOÇ. DR. İLHAN AYDIN

NESNEYE YÖNELİK PROGRAMLAMA

Nesne Tabanlı Programlama Dersi Edirne Kız Teknik ve Meslek Lisesi

BİLİŞİM TEKNOLOJİLERİ

Görsel Programlama DERS 01. Görsel Programlama - Ders01/ 1

Transkript:

ÖĞRENME FAALİYETİ 1 ÖĞRENME FAALİYETİ 1 AMAÇ Bu faaliyetle gerekli araç gereç ve ortam sağlandığında kalıtım ile çalışabileceksiniz. ARAŞTIRMA Biyoloji dersinde yer alan canlılar konusunun neden canlıları tek tek değil de sınıflara ayırarak incelediğini araştırınız. Programlama dilinin sınıf kütüphanesini nesne tabanlı programlama yazılımı ortamındaki nesne tarayıcısı (object browser) penceresiyle (Görünüm (view) menüsünden ulaşarak) inceleyiniz. Buradaki sınıflandırmanın biyolojideki canlıların sınıflandırılmasına benzeyip benzemediğini arkadaşlarınızla tartışınız. 1. KALITIM Kalıtım nesne tabanlı programlama dünyasında kilit öneme sahip bir kavramdır. Nesne tabanlı programlamada gerçek dünya problemlerini bilgisayar uygulamaları yardımıyla çözmek için bu problemleri modellemek gerekir. Sınıflar, modellemenin yapı taşlarıdır. İlerleyen konularda söz edileceği gibi bir okul yönetim uygulaması geliştirileceği düşünülsün. Uygulamada müdür, öğrenci ve öğretmenleri modellemek için sınıflardan (Okuldaki sınıflarla karıştırmayalım.) yararlanılır. Ancak hem müdür hem öğretmen hem de öğrenciler ortak özelliklere sahiptir. Örneğin, hepsinin de birer adı vardır. Müdür, öğretmen ve öğrenci sınıflarının hepsinde de ad şeklinde bir özellik kullanılırsa kod tekrarından nasıl kaçınılabilir? Bu mümkün olmaz. Bu noktada devreye kalıtım girmektedir. Bu sınıfların üstünde insan adında bir sınıf oluşturup müdür, öğretmen ve öğrenci sınıflarını da insandan türeterek bu problemin üstesinden gelinebilir. Hemen tüm problemleri modellerken benzer senaryolarla karşılaşılır ve kalıtımı yoğun bir şekilde kullanılır. Kod tekrarından kaçınmanın yegâne yolu kalıtımı kullanmaktır. Kalıtımı anladıktan sonra gerçek dünyada da aslında her şeyin kalıtımla ne kadar ilişkili olduğu görülür. Artık modellemeler kalıtım olmaksızın düşünemez hâle gelinir. 1.1. Temel Sınıflar ve Türetilmiş Sınıflar Nesne tabanlı programlama ile problemleri gerçek dünyadakine benzer tarzda nesneler şeklinde modelleyerek çözmeye çalışılır. İnşaat sektöründe bir bina nasıl inşa edilir? Önce projesi çizilir. Sonra bu proje gerçekleştirilir ve bina ortaya çıkar. Nesne tabanlı programlamada da önce sınıflar (bina örneğindeki projeye benzetilebilir) tasarlanır. Bir uygulama çok sayıda sınıf yardımıyla modellenebilir. Bu sınıflardan bazıları temel sınıf 3

bazıları da türetilmiş sınıflardır. Temel sınıf Ata sınıf olarak işlev görür. Türetilmiş sınıf ise temel sınıfın özelliklerine sahip olmanın yanında kendisi temel sınıfta bulunmayan yeni özellikler de geliştirebilir. Örneğin, girişte de bahsedildiği gibi bir okul yönetim uygulaması geliştirileceği düşünülsün. İşe okuldaki her şey modellenerek başlanır. Okulumuzda değişik rollerde insanlar vardır. Müdür, müdür yardımcısı, öğretmen, memur, hizmetli, öğrenci rolleri sayılabilir. Her insan rolü için ayrı ayrı sınıf oluşturmak yerine insan sınıfı oluşturup sonra bu sınıftan kalıtım yoluyla müdür, müdür yardımcısı, öğretmen, memur ve öğrenci sınıfları türetilebilir. Bu örnekte insan sınıfı temel sınıf, diğerleri ise türetilmiş sınıf olarak adlandırılmaktadır. class Insan //temel sınıf üyeleri class Ogrenci : Insan //türetilmiş sınıf üyeleri Örnekte görüldüğü gibi Kalıtım yoluyla türetme : (iki nokta üst üste) işlemci yardımıyla yapılmaktadır. İki noktanın solundaki sınıf (Ogrenci) türetilmiş, sağındaki ise (Insan) temel sınıftır. Burada Ogrenci sınıfı Insan sınıfından türetilmiş bulunmaktadır. Diğer bir ifadeyle Ogrenci sınıfı Insan sınıfının özel (private) olmayan tüm üyelerini kalıtım yoluyla almıştır. Türetme sonucunda Insan sınıfının özel (private) olmayan tüm alanlarını otomatik olarak Ogrenci sınıfı içermektedir. Bir sınıf doğrudan en fazla bir sınıftan türetilebilir. İki ya da daha fazla sınıftan türetilemez. Eğer böyle bir ihtiyaç olursa arayüzleri kullanmak gerekir. Ancak tüm sınıflar dolaylı olarak System.Object sınıfından türetilmektedir. Bunun belirtilmesine de gerek yoktur. Örneğin üstte oluşturulan Insan sınıfına hiç üye eklenmese bile bazı üyelere otomatik olarak sahip olduğu görülür. Bunlardan bir tanesi ToString metodudur. Aslında bütün sınıflar bu metoda sahip olur. Bu da onların dolaylı olarak System.Object sınıfından türediğini kanıtlar. Aşağıdaki resimde Class View penceresi görülüyor. Insan sınıfının temel sınıfının (Base Types) Object olduğu açıkça görülmektedir. 4

Resim 1.1: Sınıf görünümü (class view) penceresi Türetilmiş bir sınıftan başka sınıflar da türetilebilir. Ancak bunun bir şartı vardır. Sealed olarak tanımlanmış bir sınıftan başka bir sınıf türetilemez. Diğer sınıflar da aynı şekilde, türetilebilir. class Mudur : Insan //türetilmiş sınıf üyeleri class MudurYardimcisi : Insan //türetilmiş sınıf üyeleri class Ogretmen : Insan //türetilmiş sınıf üyeleri class Memur : Insan //türetilmiş sınıf üyeleri 5

1.2. Temel Sınıf Kurucularını Çağırma Türetilmiş bir sınıf, temel sınıfın tüm alanlarına sahiptir. Bu alanların başlangıçta ilk değerlerinin belirlenmesi gerekir. Bu amaçla kurucu metotlar çağrılır. Türetilmiş bir sınıftan temel sınıfa ait kurucu metodu çağırmak için base anahtar sözcüğü kullanılır. class Insan //temel sınıf üyeleri public Insan(string ad)//temel sınıf için kurucu metot //... //... class Ogrenci : Insan //türetilmiş sınıf üyeleri public Ogrenci(string ad) : base(ad)//insan(ad) temel sınıf kurucu metodunu çağırır //... //... Bu şekilde temel sınıf kurucusu çağırılmazsa derleyici varsayılan temel sınıf kurucusunu çağırmaya çalışır. Bu da başarılamazsa bir derleyici hatası oluşur. 1.3. Sınıflar Atamak Bir sınıf türü kullanarak bir değişken bildirmek ve sonra bir nesne yaratarak bu değişkene atamak için aşağıdaki söz dizimi kullanılır. Aşağıdaki hiyerarşik yapıya sahip olunsun. class Insan //temel sınıf üyeleri public double Boy, Kilo; public string Ad; public Insan(string ad)//temel sınıf için kurucu metot this.ad = ad; this.boy = 0.45; 6

this.kilo = 3.5; public void Buyu() Boy += 0.5; Kilo += 0.5; class Ogrenci : Insan //türetilmiş sınıf üyeleri public Ogrenci(string ad) : base(ad)//insan(ad) temel sınıf kurucu metodunu çağırır new public void Buyu() this.boy += 1.5; this.kilo += 1.5; public void Oku() //Oku metodu kodları class Ogretmen : Insan public Ogretmen(string ad) : base(ad) Şöyle bir bildirim ve atama gerçekleştirebiliriz: Ogrenci birogrenci = new Ogrenci("Ali UZUN"); Burada birogrenci değişkeni Ogrenci türünde bildiriliyor ve new sözcüğü ile oluşturulan nesne birogrenci değişkenine atanıyor. 7

Programlama dilindeki tür denetim kuralları bir türdeki nesneyi farklı bir türde bildirilmiş bir değişkene atamaya izin vermez. Ogrenci birogrenci = new Ogrenci("Ali UZUN"); Ogretmen birogretmen = birogrenci; //hata Yukarıdaki örnek derleme zamanı hatasına neden olur. Derleyici Ogrenci nin Ogretmen e açıkça dönüştürülemeyeceğini bildiren bir hata mesajı görüntüler. Bunun yanı sıra tür olarak kalıtım hiyerarşisinin üst sırasında yer alan bir türde tanımlanmış bir değişkene alt sıradaki bir türde oluşturulmuş nesne atanabilir. Örneğin, Ogrenci birogrenci = new Ogrenci("Ali UZUN"); Insan birinsan = birogrenci; //geçerli bir atama Ogrenci sınıfından tanımlanmış birogrenci, Insan sınıfından tanımlanmış birinsan değişkenine atanabilir çünkü Insan sınıfı hiyerarşinin üst sırasında yer almaktadır. Aslında Ogrenci sınıfı Insan sınıfının tüm üyelerine sahip ve sadece birkaç fazlası vardır. diplomanotu ve Oku üyeleridir. Yalnız üstteki örnekte birinsan değişkeni aracılığı ile sadece Insan sınıfının üyelerine erişilebilir. Yani Ogrenci sınıfındaki Oku metoduna erişmek mümkün olamaz. 1.4. New Metodu Programcının çok zorlandığı durumlardan bir tanesi de sınıflara ve sınıfların üyelerine benzersiz ve anlamlı adlar bulmaktır. Eninde sonunda sınıf hiyerarşisi içerisinde temel sınıfa ait bir metodun adı türemiş sınıfta kullanılacaktır. Örneğin, class Insan //temel sınıf üyeleri public double Boy, Kilo; public string Ad; public Insan(string ad)//temel sınıf için kurucu metot this.ad = ad; this.boy = 0.45; this.kilo = 3.5; 8

public void Buyu() Boy += 0.5; Kilo += 0.5; class Ogrenci : Insan //türetilmiş sınıf üyeleri public Ogrenci(string ad) : base(ad)//insan(ad) temel sınıf kurucu metodunu çağırır new public void Buyu() this.boy += 1.5; this.kilo += 1.5; public void Oku() //Oku metodu kodları Insan temel sınıfında yer alan Buyu metodu Ogrenci türemiş sınıfında da kullanılmaktadır. Derleyici bu durumda Insan sınıfındaki Buyu metodunun gizlendiğini belirten bir uyarı görüntüler. Bu uyarı aynı zamanda new sözcüğünü kullanarak bu uyarının kaldırılabileceğini de belirtir. İşte türemiş Ogrenci sınıfındaki Buyu metodunun başında new sözcüğünü kullanma nedeni budur. Burada derleyiciye bilinçli olarak temel sınıftaki Buyu metodunun gizlendiği bildirilmiş olunuyor. 1.5. Virtual (Sanal) Metodu Temel sınıfa ait bir metodun bazen türemiş sınıfta farklı bir şekilde kullanılması gerekebilir. Bu durumda temel sınıfın söz konusu metodu türemiş sınıfın değiştirip kullanabileceği yönünde izin vermesi gerekir. Bu izin, metodun temel sınıfta virtual olarak tanımlanması sonucu verilmektedir. Diğer bir ifadeyle temel sınıfta virtual olarak tanımlanmış bir metodun türemiş sınıfta yeniden yazılabileceği belirtilmiş olunuyor. Örneğin, 9

public class Sekil public const double PI = Math.PI; protected double x, y; public Sekil() public Sekil(double x, double y) this.x = x; this.y = y; public virtual double Alan() return x * y; Sekil sınıfına ait alan adında bir metot olsun. Örnekte alan metodunun virtual tanımlandığına dikkat edilmelidir. Sekil sınıfından türeyecek diğer sınıflar içerisinde alan metodunun değiştirilerek yeniden yazılmasına burada izin verilmiş bulunuluyor. 1.6. Override (Geçersiz Kılma) Metodu Temel sınıfta virtual tanımlanmış bir metodun türemiş sınıfta yeniden yazılması için (geçersiz kılma) override sözcüğü kullanılır. Temel sınıfta virtual tanımlanmamış ya da static tanımlanmış olan üyeler (metot, özellik, dizinleyici ya da olay) türemiş sınıfta yeniden yazılamaz (Geçersiz kılınamaz.). 1.4 başlığı altında verilen örneği şu şekilde genişletilebilir: public class Daire : Sekil public Daire(double r) : base(r, 0) public override double Alan() return PI * x * x; 10

class Kure : Sekil public Kure(double r) : base(r, 0) public override double Alan() return 4 * PI * x * x; class Silindir : Sekil public Silindir(double r, double h) : base(r, h) public override double Alan() return 2 * PI * x * x + 2 * PI * x * y; Bu örnekte Daire, Kure ve Silindir sınıfları Sekil temel sınıfından türetilmişlerdir. Hepsinde de Sekil sınıfında virtual tanımlanan alan metodu yeniden yazılmıştır. Bu yeniden yazma (geçersiz kılma) esnasında override sözcüğünün kullanıldığına dikkat ediniz. Ayrıca burada dikkat edilmesi gereken nokta virtual ve override metotların imzalarının (dönüş türleri ile birlikte parametrelerinin tür ve sayıları) aynı olması gerekliliğidir. Ayrıca temel sınıfta virtual, abstract ya da override olarak tanımlanmış metotlar türemiş sınıfta geçersiz kılınabilir. Bir diğer önemli nokta da override metotlar new, static ya da virtual sözcükleri ile tanımlanamaz. Son olarak virtual metodun erişim belirteci override sırasında değiştirilemez. Yani temel sınıfta metot public ise türemiş sınıfta da public, protected ise protected kalmalıdır. 11

1.7. Protected (Korumalı) Erişim Protected sözcüğü bir erişim belirtecidir. Yani bir sınıfın üyelerine kalıtım hiyerarşisi içinde o sınıftan türemiş diğer sınıfların erişebileceğini belirtir. Hiyerarşi dışından ise kimse protected üyelere erişemez. Benzer şekilde erişimi denetleyen public sözcüğü bir üyeye herkesin erişebileceğini, private sözcüğü ise sınıf dışından üyeye kimsenin erişemeyeceğini belirtir. Programlama dili tasarımcıları, sınıflar içerisinde yer alan üyelere erişim konusunda programcılara tam bir özgürlük sağlar. Ancak nesne tabanlı programlama belgeleri alanların private tutulmasını, alanlara erişimin özellik adı verilen özel metotlarla yapılmasını önerir. 12

ÖLÇME VE DEĞERLENDİRME ÖLÇME VE DEĞERLENDİRME Aşağıdaki soruları dikkatlice okuyunuz ve doğru seçeneği işaretleyiniz. 1. Temel sınıf ile türetilmiş sınıf arasında kullanılan ayıraç aşağıdakilerden hangisidir? A) : (iki nokta üst üste) B) ; (noktalı virgül) C), (virgül) D). (nokta) 2. Bir sınıfın en fazla kaç sınıftan kalıtım yoluyla türetilebileceğinin sayısı aşağıdakilerden hangisidir? A) 4 B) 3 C) 2 D) 1 3. Aşağıdakilerden hangisi türetilmiş bir sınıfın temel sınıftan kalıtımla alamayacağı üye için kullanılan erişim türüdür? A) Ortak (public) B) Özel (private) C) İç (internal) D) Korumalı (protected) 4. Temel sınıf kurucusunu çağırmak için kullanılan ayrılmış sözcük aşağıdakilerden hangisidir? A) this B) as C) base D) is 5. Temel sınıfta virtual tanımlanmış bir metodun türemiş sınıfta yeniden yazılması için (geçersiz kılma) hangi sözcük kullanılır? A) override B) new C) base D) void DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise bir sonraki öğrenme faaliyetine geçiniz. 22

ÖĞRENME FAALİYETİ 2 AMAÇ ÖĞRENME FAALİYETİ 2 Bu faaliyetle gerekli araç gereç ve ortam sağlandığında arayüzleri (interface) kullanabileceksiniz. ARAŞTIRMA Arayüz ve kontrat kelimelerinin birbirleri ile ilişkisini araştırıp arkadaşlarınızla tartışınız. Bir programcı ekibi içinde yer alıyor olsaydınız yazacağınız kodlardaki standartları belirlemek için ne yapardınız? Sınıfta arkadaşlarınızla tartışınız. Tanıyorsanız bir programcı ekibi ile görüşerek birlikte çalışmanın zorluklarını ve nasıl çözdüklerini içeren bir söyleşi yapınız. Sonuçları bir rapor hâline getirip sınıfa sununuz. 2. ARAYÜZLER Bir sınıftan kalıtımla almak güçlü bir mekanizmadır, asıl kalıtımın gücü bir arayüzden kalıtımla almasında yatar. Bir sınıf kalıtımla sadece bir sınıftan türetilebilir ancak bu kısıtlama kalıtımla arayüzden türetme söz konusu olduğunda ortadan kalkar yani bir sınıf birden çok arayüzden kalıtımla türeyebilir. Arayüzler sınıflar gibi kod ve veri içermez, sadece tanım içerir. Aslında soyut sınıflar arabirimlere benzerler ancak soyut sınıflar kod ve veri içerebildikleri için arayüzlerden ayrılır. Ancak çoğu zaman arayüzler soyut sınıflarla beraber kullanılarak güçlü uygulamalar geliştirilir. 2.1. Arayüz Tanımlama Arayüz tanımlamak için class (kılas) ya da struct (sıtrakt) sözcükleri yerine interface (interfeys) sözcüğü kullanılır. Arayüz içinde metotları aynen bir sınıf (class) ya da yapı (struct) içerisinde olduğu gibi bildirilir. Farklı olarak herhangi bir erişim belirteci (public (pablik), private (priveyt) ya da protected (protektıd)) kullanılmaz ve metot gövdesi noktalı virgülle ayrılır. Örneğin, interface IComparable int CompareTo(object obj); 23

Arayüz isminin başında I harfi kullanıldığına dikkat edilmelidir. Bu kullanılan sınıfın bir arayüz olduğunu anlamamıza yarayan bir isim kullanma tekniğidir. Bu sayede, sınıfların kalıtımsal olarak aldığı elemanların arayüz olup olmadığı daha kolayca anlaşılabilir. Arayüzlerin sahip olabileceği üyeler: Özellikler (properties) Metodlar (methods) Olaylar (events) İndeksleyiciler (indexers) Arayüzlerin sahip olamayacağı üyeler: Yapıcılar (constructors) Yokediciler (destructors) Alanlar (fields) 2.2. Arayüz Kısıtlamaları Bir arayüzün hiçbir zaman bir uygulama (tanımlama dışında deyim ve ifadeler) içermeyeceği unutulmamalıdır. Bu durumun doğal sonucu olarak aşağıdaki kısıtlamalar ortaya çıkar: Bir arayüz için herhangi bir alan (field) tanımlanamaz (statik olsa bile). Çünkü alan bir sınıf ya da bir yapının uygulama detayıdır. Bir arayüz içinde kurucu (constructor) tanımlamaya da izin verilmez. Bu da uygulama detayı kabul edilir. Bir arayüz içinde bir yıkıcı (destructor) da tanımlanamaz. Bir metot için bir erişim belirteci de belirtilemez. Çünkü bir arayüzdeki tüm metotlar dolaylı olarak ortaktır (public). Bir arayüz içerisinde hiçbir türü yuvarlanamaz. Bir başka deyişle arayüzler sınıf, yapı ya da numaralandırma içeremez. Bir arayüzü bir sınıf ya da yapıdan kalıtımla alamazsınız yani türetemezsiniz. Arayüzler,arayüzlerden türeyebilir. Yapılar ve sınıflar uygulama içerdikleri için bu kısıtlama olmasaydı üstteki bazı kısıtlamalar ihlal edilirdi. 2.3. Bir Arayüz Uygulamak Bir arayüzü uygulamak için arayüzden kalıtımla alan ve arayüzde belirtilen tüm yöntemleri sağlayan bir sınıf ya da yapı bildirilir. Öğrenme faaliyeti -1 içinde temel sınıf olan insan hatırlanmalıdır. Bu sınıfın içerisinde Buyu adında bir metot kullanılmıştı. Insan sınıfı IInsan adında bir arayüzü uyguluyor olsun. Bu arayüz de aşağıdaki gibi tanımlanmış olsun. interface IInsan void Buyu(); 24

Arayüz adlarına I harfi ile başlamak kural olmasa bile neredeyse kural hâline gelmiş bir alışkanlıktır. Hiçbir sakıncası bulunmadığı gibi programcılar topluluğuna uyum sağlamayı kolaylaştırır. Insan sınıfının bu arayüzü uygulaması için bu arayüzden kalıtım yoluyla türetilsin: class Insan : IInsan public void Buyu() //metot kodları Bir arayüz herhangi bir sınıfa uygulandığında (sınıf ilgili arayüzden türetildiğinde) o sınıfı tamamen kendisine benzemeye zorlayacaktır. Bu da birden fazla sınıfı aynı arayüzden türeterek bunlara tek bir değişken üzerinden erişebilme imkânı sağlayacaktır. Örneğin,.Net,.NET Framework içerisinde yer alan Icomparable arayüzü iki nesnenin değerini karşılaştırır ve değerleri aynı ise 0, farklı ise -1 değerini üretir. Ancak bu karşılaştırmayı yapabilmesi için karşılaştırılan türlerin Icomparable arayüzünü uyguluyor olması gerekir. Bu ifade aslında bir kural tanımıdır ve şu anlama gelmektedir : Eğer sınıftan oluşturulacak nesneleri karşılaştırılabilir yapmak isteniyorsa bu sınıfı Icomparable arayüzünden türetmelisiniz. Aşağıdaki örnekte IComparable arayüzünü uygulayan int türünden iki değer karşılaştırılmaktadır. static void Main(string[] args) int s1 = 3; int s2 = 3; Console.WriteLine(s1.CompareTo(s2)); Program çalıştırıldığında ekrana 0 değerini yazacaktır. Çünkü s1 ve s2 nin değerleri aynıdır. Burada int türü için Icomparable arayüzünü uygular denilebilir. Siz de kendi hazırladığınız bir sınıf nesneleri için birbirleri ile karşılaştırılabilir olmasını sağlayabilirsiniz. Aşağıdaki örnekte Daire isminde bir sınıf yazılmış ve bu sınıfa IComparable arayüzü uygulanmıştır. Böylece Daire sınıfından oluşturulan iki ayrı nesneyi karşılaştırma imkânına sahip olunur. class Daire:IComparable int yaricap; //Sınıfımıza ait field(alan) public Daire(int yaricap)//sınıfın kurucu metodu 25

this.yaricap = yaricap; public int CompareTo(object daire1) //Arayüzden gelen metodumuz. //metoda gelen daire1 değişkeni object olduğu için öncelikle kendi türüne dönüştürüyoruz. Daire karsilastirilacak_daire = daire1 as Daire; //yarıçapı bu dairenin yarıçapı ile aynı ise 0, farklı ise -1 gönderiyoruz. return (yaricap == karsilastirilacak_daire.yaricap)? 0 : -1; class Program static void Main(string[] args) Daire daire_1 = new Daire(3);//Birinci daire nesnemiz Daire daire_2 = new Daire(2);//İkinci daire nesnenimiz //Karşılaştırılan her iki daire nesnemizinde yarıçapı faklı olduğu için ekrana -1 yazacaktır. Console.WriteLine(daire_1.CompareTo(daire_2)); Daire isimli sınıfımız IComparable arayüzünü uyguladığı için CompareTo isimli, dışarıdan object alan ve int değer döndüren bir metoda sahip olmalıdır. Bu kural IComparable arayüzü tarafından tanımlanmış bir kuraldır. Siz arayüzü sınıfınıza uygularsanız bu kuralı kabul etmiş sayılırsınız. Bu yüzden IComparable arayüzünden türetilmiş olunan sınıfta bu kurala uygun bir metot tanımlamak zorunda kalınır. Bir arayüzü uygulandığında her metodun kendine uygun bir arayüz metoduyla tam olarak eşleşmesi garantiye alınmalıdır. Metot adları ve dönüş türleri kesin olarak eşleşmelidir. Parametreler (ref ve out anahtar sözcükleri dahil) tam olarak eşleşmelidir. Arayüz tanımı ve arayüz uygulaması arasında bir fark varsa uygulama derlenmez. Arayüzden türetilen sınıf içerisinde oluşturulan arayüze ait metotlar mutlaka public olarak tanımlanmalıdır(örneğin, Daire sınıfı için CompareTo metodu private yapılıarsa derleme hatası alınır.). Bir sınıf hem bir sınıftan devralıyor hem de bir arayüzü uyguluyorsa aşağıdaki gibi kodlanır: class Ogrenci : Insan, IInsan public void Buyu() //metot komutları 26

Önce sınıf adı belirtilir. Bunu bir virgül takip eder. Daha sonra arayüz adı yazılır. 2.4. Bir Sınıfa Arayüz İle Ulaşma Hiyerarşide üst sıralarda tanımlanmış bir sınıf değişkeni ile bir nesneye başvurulabildiği gibi sınıfın uyguladığı bir arayüz olarak tanımlanmış bir değişken kullanarak da nesneye ulaşılabilir. Hatırlanırsa Öğrenme Faaliyeti - 1 de Ogrenci birogrenci = new Ogrenci("Ali UZUN"); Insan birinsan = birogrenci; //Geçerli bir atama. Ogrenci Insan dan türetiliyor. örneğiyle Insan tipinde bildirilmiş olan birinsan değişkeni ile Ogrenci tipinde bildirilmiş olan birogrenci nesnesine başvurmuştuk. Benzer şekilde; Ogrenci birogrenci = new Ogrenci(); IInsan birinsan = birogrenci; //Geçerli bir atama. Ogrenci IInsan ı uyguluyor. IInsan tipinde bildirilmiş olan birinsan arayüz değişkeni ile Ogrenci tipinde bildirilmiş olan birogrenci nesnesine başvurulabilir. Çünkü Ogrenci sınıfı IInsan arayüzünü uygulamaktadır. Bir nesneye bir arayüz üzerinden başvurma yöntemi faydalıdır. Çünkü türler belirtilen arayüzü uyguladığı sürece, parametre olarak farklı türler alabilen metotları tanımlayabilmeyi sağlar. Örneğin, aşağıda gösterilen Sil metodu, IInsan arayüzünü uygulayan herhangi bir bağımsız değişken alabilir. static void Sil(IInsan birogrenci) //... Bu örnekte bağımsız değişken IInsan arayüzünü uygulayan herhangi bir nesne olabilir. Bir arayüz üzerinden bir nesneye başvurulduğunda sadece arayüz içerisinde tanımlanan metotlar kullanılabileceği unutulmamalıdır yani Ogrenci sınıfı IInsan arayüzünde tanımlanmayan Oku metoduna sahip olsaydı bu metot kullanılamayacaktı. 2.5. Soyut (Abstract) Sınıflar IInsan arayüzünü uygulayan Ogrenci ve Ogretmen sınıflar olsun. IInsan arayüzünde de Oku metodu tanımlanmış olsun. Bu durum hem Ogretmen hem de Ogrenci iki sınıfta da tamamen aynı olacak, Oku metodunu uygulayacaklardır. Burada bir uyarı ile karşı karşıya kalmak demektir. Çünkü kod tekrar etmektedir. interface IInsan 27

void Oku(); void Konus(); class Ogrenci : IInsan public void Oku() //... public void Konus() //... class Ogretmen : IInsan public void Oku() //.. public void Konus() //... Oku metodunun içeriği sınıfa göre değişmeyecektir. Bir öğretmenin okuması ile öğrencinin okuması arasında ne fark olabilir Ama aynı durum Konus metodu için geçerli olmayacaktır. Çünkü Ogretmen ve Ogrenci sınıfları Konus metodunu kendilerine özgü gerçekleştireceklerdir (Herkesin ses tonu ve şivesi gibi özellikler değişkendir.). Yinelemeden kaçınmak ve kodun bakımını kolaylaştırmak için kodu yeniden düzenlenmelidir. Bunun yolu ortak uygulamayı özellikle bu amaç için oluşturulmuş yeni bir sınıf içerisine taşımaktır. Bu tasarım şu şekilde değiştirilebilir: interface IInsan void Konus(); class OkuyanInsan public void Oku() //... class Ogrenci : OkuyanInsan, IInsan 28

class Ogretmen : OkuyanInsan, IInsan Burada OkuyanInsan adında bir sınıf oluşturuldu ve Oku metodu buraya taşındı. Sorun çözülmüş gibi görünse de hâlâ bir problem var. OkuyanInsan sınıfının örneğini oluşturmak mümkündür. Bu çok mantıksızdır. Biz onu sadece kendisinden Ogrenci ve Ogretmeni türetmek için oluşturuldu ve ortak uygulama (Oku eylemi) sağlaması amaçlandı. Yani OkuyanInsan sınıfı kendi haklarına sahip bir girişten çok ortak işlevselliklerin bir soyutlaması olacaktır. Bir sınıfın oluşumlarının yaratılmasına izin verilmediğini belirtmek için abstract anahtar sözcüğünü kullanarak açıkça sınıfın soyut olduğunu bildirmek gerekir. Örneğin, abstract class OkuyanInsan public void Oku() //Oku metodu soyut olarak tanımlanan OkuyanInsan sınıfı içerisinde public olarak gövdesi ile birlikte oluşturuluyor.böylece bu sınıftan türetilen tüm sınıflar için burada yazılan Oku işlevi kalıtım yolu ile geçecektir. class Ogrenci : OkuyanInsan, IInsan //OkuyanInsan sınıfında tanımlanan Oku metodu public olduğu için kalıtım yolu ile Ogrenci sınıfımıza da geçecektir. public void Konus()//IInsan arayüzünden gelen metodum Console.WriteLine("Soyut sınıfların nesnesi oluşturulabilir mi?"); class Ogretmen : OkuyanInsan, IInsan //OkuyanInsan sınıfında tanımlanan Oku metodu public olduğu için kalıtım yolu ile Ogretmen sınıfımıza da geçecektir. public void Konus()//IInsan arayüzünden gelen metodum Console.WriteLine("Soyut sınıfların nesnesi oluşturulamaz"); 29

Bir OkuyanInsan nesnesi oluşturmaya çalışılırsa kod derlenmez. OkuyanInsan birinsan = new OkuyanInsan();//kod derlenmez.abstract olarak tanımlanan sınıflar nesnesi oluşturulmak için değil kendisinden türetme yapılması amacıyla oluşturulmaktadır. Ancak aşağıdaki kullanımlar geçerli olacaktır. OkuyanInsan ogretmen = new Ogretmen();//Kalıtımdan dolayı bu kullanım geçerlidir. OkuyanInsan ogrenci = new Ogrenci();//Kalıtımdan dolayı bu kullanım geçerlidir. Yukarıdaki örnekte Ogretmen ve Ogrenci sınıfları hem OkuyanInsan soyut sınıfından hem de IInsan arayüzünden türetildi. Aslında soyut sınıfı biraz değiştirilerek IInsan arayüzünün işlevini de ona yaptırabilirdi. Örnek aşağıdaki gibi değiştirilsin. //IInsan arayüzünde yer alan Konus metodunu soyut sınıfımız içerisinde soyut olarak işaretliyoruz. abstract class OkuyanInsan public void Oku() //... public abstract void Konus(); //abstract sınıf içerisinde abstract olarak işaretlenmiş üyeler türeyen sınıfta mutlaka override edilmelidir. Zaten bizim isteğimiz Ogrenci ve Ogretmen sınıfları için Konus metodunun olması ancak her iki sınıf için farklı davranış göstermesidir. class Ogrenci : OkuyanInsan // OkuyanInsan soyut sınıfımızda yer alan soyut olarak işaretlenmiş Konus metodumuzu burada geçersiz kılıyoruz. public override void Konus() Console.WriteLine("Soyut sınfların nesnesi olabilir mi?"); class Ogretmen : OkuyanInsan // OkuyanInsan soyut sınıfımızda yer alan soyut olarak işaretlenmiş Konus metodumuzu burada geçersiz kılıyoruz. public override void Konus() Console.WriteLine("Soyut sınıfların nesnesi olamaz."); 30

Daha önceki örnekte Konus metodu IInsan arayüzünde tanımlanmış, Oku metodu ise soyut sınıf olan OkuyanInsan sınıfı içerisinde gövdesi ile birlikte yazılmıştı. Soyut sınıf içerisinde yazılan bir üye abstract olarak işaretlenirse arayüz içerisinde tanımlanan üye gibi davranacaktır. Yani kendisinden türetilen sınıfta bu üyenin gerçekleştirilmesini zorunlu kılar (Yukarıdaki örnekte OkuyanInsan soyut sınıfı içerisinde yer alan Konus isimli metodun Ogretmen ve Ogrenci sınıflarında gerçekleştirilmesinin zorunlu olması gibi). Bu sayede örnek için IInsan arayüzüne ihtiyaç kalmamıştır. Soyut sınıf içerisinde yer alan bir üyenin türeyen sınıfta gerçekleştirilmesi zorunlu kılınması istenirse üyeyi abstract olarak işaretlenmelidir. Kendi sınıf hiyerarşisi içerisinde kod tekrarını önleyecek ortak işlevselliklerin bir soyutlamasını oluşturmak için abstract sınıflar oluşturulabilir. 2.6. Mühürlenmiş (Sealed) Sınıflar Kalıtımı her zaman akıllıca kullanmak çok kolay olmamaktadır. Bir arayüz ya da soyut bir sınıf oluşturursa gelecekte kalıtımla alınacak bir şeyler yazılıyor demektir. Gelecek önceden tahmin edilemez. Pratik yaptıkça ve deneyim kazandıkça esnek, kullanımı kolay arayüz, soyut sınıflar ve sınıflar hiyerarşisi oluşturma becerisi geliştirilebilir. Bu çok çaba gerektirir ve ayrıca modellediği problemi çok iyi anlamış olmak şarttır. Bunu yapmanın başka bir yolunu bulmak için temel bir sınıf olarak kullanmak üzere oluşturulmadığı sürece bir sınıftan kalıtımla alınması engellenebilir. Bunun için programlama dili sealed anahtar sözcüğü sunmaktadır. Örneğin, sealed class Ogrenci : OkuyanInsan, IInsan Artık Ogrenci sınıfından başka bir sınıf türetmenin imkânı kalmamıştır. Bu sözcük sınıfın hâlihazırda mühürlenip kapatıldığını belirtir. 31

ÖLÇME VE DEĞERLENDİRME ÖLÇME VE DEĞERLENDİRME Aşağıdaki soruları dikkatlice okuyunuz ve doğru seçeneği işaretleyiniz. 1. Bir arayüz tanımlamak için kullanılan sözcük aşağıdakilerden hangisidir? A) enum B) interface C) class D) struct 2. Bir arayüzün içerebileceği üye aşağıdakilerden hangisidir? A) Değişken bildirimleri B) Metot uygulamaları (deyim ve ifadeleri) C) Sınıf tanımları D) Metot tanımları 3. Aşağıdakilerden hangisi bir arayüz kısıtlaması değildir? A) Arayüz içinde alan (field) tanımlanmaz. B) Arayüz içinde kurucu (constructor) tanımlanmaz. C) Arayüz içinde metot (method) tanımlanmaz. D) Arayüz içinde yıkıcı (destructor) tanımlanmaz. 4. Bir arayüzü uygularken aşağıdakilerden hangisi bir kural veya alışkanlık olarak gerekli değildir? A) Parametre adları arayüzde ve uygulayan sınıfta aynı olmalıdır. B) Metot adları ve dönüş türleri kesin olarak eşleşmelidir. C) Parametreler (ref ve out anahtar sözcükleri dahil) tam olarak eşleşmelidir. D) Metot adı arayüz adıyla başlar. 5. IInsan adında bir arayüzünüz var. Bu arayüzü Ogrenci, Mudur ve Ogretmen adında üç sınıf uyguluyor olsun. birinsan adında IInsan değişkeni, birogrenci adında Ogrenci değişkeni, birogretmen adında Ogretmen değişkeni, birmudur adında da Mudur değişkeni bildirildiği varsayılsın. Buna göre aşağıdaki atamalardan hangisi geçerli değildir? A) birinsan = birmudur; B) birinsan = birogrenci; C) birinsan = birogretmen; D) birmudur = birinsan; DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise Modül Değerlendirme ye geçiniz. 39

MODÜL DEĞERLENDİRME MODÜL DEĞERLENDİRME Aşağıdaki soruları dikkatlice okuyunuz ve doğru seçeneği işaretleyiniz. 1. İnsan adında bir temel sınıf olsun. Ögrenci sınıfı da Insan sınıfından türetildi. Ogrenci sınıfı kurucuda parametre olarak öğrenci adını alsın. birogrenci adında Insan türünde bir değişken bildirip Ogrenci sınıfından bir nesneyi birogrenci değişkenine atanmak isteniyor. Aşağıdakilerden hangisi bu işi doğru bir şekilde gerçekleştirir? A) Ogrenci birogrenci = new Ogrenci("Ali UZUN"); B) Insan birogrenci = new Insan("Ali UZUN"); C) Ogrenci birogrenci = new Insan("Ali UZUN"); D) Insan birogrenci = new Ogrenci("Ali UZUN"); 2. Temel sınıfın sahip olduğu bir metodun imzası bakımından aynısına türemiş sınıf da sahip olursa derleyici bir uyarı (warning) görüntüler. Bu uyarıyı kaldırmak için kullanılan sözcük aşağıdakilerden hangisidir? A) protected B) virtual C) new D) override 3. Temel sınıfta sanal bir metot yazarak daha sonra türemiş sınıfta da bu metodu geçersiz kılınmak isteniyor. Bu sanal metodu tanımlamak için kullanılan sözcük aşağıdakilerden hangisidir? A) protected B) virtual C) new D) override 4. Temel sınıfta sanal bir metot yazarak daha sonra türemiş sınıfta da bu metodu geçersiz kılınmak isteniyor. Bu sanal metodu türemiş sınıfta geçersiz kılmak için kullanılan sözcük aşağıdakilerden hangisidir? A) protected B) virtual C) new D) override 5. Temel sınıfın bir üyesine, sadece bu sınıftan türemiş bir sınıfın erişebilmesi isteniyor. Bu üyeyi tanımlamak için kullanılabilecek erişim belirteci aşağıdakilerden hangisidir? A) Ortak (public) B) İç (internal) C) Korumalı (protected) D) Özel (private) 6. Bir sınıfı soyut tanımlamak için kullanılan sözcük aşağıdakilerden hangisidir? 40

A) abstract B) virtual C) static D) sealed 7. Bir sınıfı kendisinden kalıtım yoluyla başka bir sınıf türetilemeyecek şekilde tanımlamak için kullanılan sözcük aşağıdakilerden hangisidir? A) virtual B) abstract C) static D) sealed 8. Arayüz adlarını I harfiyle başlatmanın yararı aşağıdakilerden hangisi olabilir? A) Derleyici bunun bir arayüz olduğunu anlar. B) Programcılar arasında uyum sağlanır. C) Bir sınıfı bir arayüzden kesin olarak ayırır. D) Bir yapıyı bir arayüzden kesin olarak ayırır. 9. Arayüzde tanımlanan metotlarda erişim belirteci belirtilmemesinin nedeni aşağıdakilerden hangisi olabilir? A) Bir arayüzdeki tüm metotlar dolaylı olarak ortaktır. B) Bir arayüzdeki tüm metotlar dolaylı olarak özeldir. C) Bir arayüzdeki tüm metotlar dolaylı olarak korumalıdır. D) Bir arayüzdeki tüm metotlar tam sayı değer döndürür. 10. Bir arayüzün içerebileceği tür aşağıdakilerden hangisidir? A) Sınıf B) Yapı C) Numaralandırma D) Yukarıdakilerin hiçbiri 11. Bütün üyeleri soyut olarak işaretlenmiş bir soyut sınıf aşağıdakilerden hangisine benzer? A) Protected olarak işaretlenmiş üyelere B) Tüm üyeleri virtual sözcüğü ile işaretlenmiş temel sınıflara C) Arayüzler D) Yukarıdakilerin hiçbiri DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise bir sonraki modüle geçmek için öğretmeninize başvurunuz. 41

ÖĞRENME FAALİYETİ 1 AMAÇ ÖĞRENME FAALİYETİ 1 Bu faaliyetle gerekli araç, gereç ve ortam sağlandığında özellikler ile çalışabileceksiniz. ARAŞTIRMA Nesne tabanlı programlamada sınıf tanımlamada kullanılan metot ve özellik arasında ne farkı vardır? Araştırınız. Gerçek hayattaki nesnelerin özellikleri ile bir sınıf tanımlamada kullanılan özelliklerin benzerliği var mıdır? 1. ÖZELLİKLER Bu bölümde, bir sınıftaki alanları gizlemek için özellikleri nasıl tanımlayacağınız ve kullanacağınız ele alınacaktır. Önceki bölümlerde, bir sınıf içindeki alanları özel yapmanız ve bu alanlardaki değerleri saklamak ve yeniden elde etmek için yöntemler sağlamanız gerektiği vurgulanmıştı. Bu yaklaşım, alanlara güvenli ve kontrollü bir erişim ve izin verilen değerlere ilişkin ek mantık ile kuralları kapsüllemenizi sağlar. Bununla birlikte, bu yolla bir alana erişim için söz dizimi doğal değildir. Bir değişken okumak ya da yazmak istediğinizde, normal olarak bir atama ifadesi kullanırsınız. Bu nedenle bir alanda (sonuç olarak bir değişken) aynı etkiye erişmek için bir yöntem çağırmak biraz acemiliktir. Özellikler bu uygunsuzluğu gidermek için tasarlanmıştır. 1.1. Metotlar İle Kapsülleme Alanları gizlemenin (kapsüllemenin) yollarından bir tanesi de metotları kullanmaktır. Bilgisayar ekranındaki bir noktayı x ve y koordinatları ile gösteren aşağıdaki şekilde bir yapımız olsun. x koordinatı için geçerli aralığın 0 ile 1280 arasında olduğunu y koordinatı için ise geçerli aralığın 0 ile 1024 arasında olduğunu varsayalım. struct EkranPozisyonu public EkranPozisyonu(int x, int y) this.x = aralikdenetlex(x); this.y = aralikdenetley(y); public int X; public int Y; 3

private static int aralikdenetlex(int x) if (x < 0 x > 1280) throw new ArgumentOutOfRangeException("X"); return x; private static int aralikdenetley(int y) if (y < 0 y > 1024) throw new ArgumentOutOfRangeException("Y"); return y; Bu yapı ile ilgili en önemli problem kapsüllemenin altın kuralına uymamasıdır. Yani veri tipi özel (private) değildir. Ortak (public) veri kullanımı sınırlılıkları olan bir uygulamadır. Çünkü kullanımı denetlenmez. Örneğin Ekran Pozisyonu kurucu aralığı parametrelerini denetler. Ancak böyle bir denetim ortak alanlara (X ve Y) uygulanmaz. Uygulamada programlama hatası sonucu olarak X veya Y konum aralığının dışına düşer. EkranPozisyonu orijin = new EkranPozisyonu(0, 0); int xpos = orijin.x; orijin.y = -100; //hata! Y 0-1024 aralığında olmalı Bu problemi çözmek için kullanılan yöntemlerden bir tanesi, alanları özel yapmak ve her özel alanın değerini okumak ve yazmak için birer erişimci ve değiştirici metot eklemektir. Değiştirici yöntemler daha sonra yeni alan değerlerinde aralık denetimi yapabilir. Örneğin aşağıdaki kod X alanı için bir erişimci (OkuX) ve bir değiştirici (YazX) metot içerir. YazX in parametre değerini nasıl denetlediğine dikkat ediniz. struct EkranPozisyonu... public int OkuX() return X; public void YazX(int yenix) this.x = aralikdenetlex(yenix);... 4

Kod artık aralık denetlemelerini başarıyla uygular. Bununla birlikte Ekran Pozisyonu artık doğal bir alan benzeri söz dizimine sahip değildir. Metot temelli bir söz dizimi ortaya çıkmıştır. Aşağıdaki örnek X in değerini 10 artırır. Bunu yapmak için OkuX ile önce X in değerini okumalı, arttırdıktan sonra da YazX ile X in değerini yazmalıyız. int xpos = orijin.okux(); orijin.yazx(xpos + 10); Bu işlemi X alanı ortak (public) olduğunda aşağıdaki örnekte görüldüğü gibi gerçekleştiriyoruz: orijin.x += 10; Şüphesiz bu durumda alanları kullanmak daha kısa, daha açık ve daha kolaydır. Ne yazık ki ortak alanları kullanmak kapsüllemeyi kırar. Özellikler bu noktada devreye girerek her iki örneğin iyi yönlerini birleştirir. Yani alan benzeri bir söz dizimi kullanımına izin verirken kapsüllemeyi de sürdürür. 1.2. Özellikleri Kullanma Bir özelliği bir deyimde kullandığınızda onu ya bir okuma bağlamında (değerini değiştirmediğiniz durumlar) ya da bir yazma bağlamında (değerini değiştirdiğiniz durumlar) kullanırsınız. Ekran Pozisyonu 2 (Ekran Pozisyonu yapısının özellik kullanan sürümü) yapısının özelliklerini kullanarak okuma ve yazma örneğine ait kodlar aşağıda verilmiştir: struct EkranPozisyonu2 public EkranPozisyonu2(int x, int y) this.x = aralikdenetlex(x); this.y = aralikdenetley(y); private int x; public int X get return this.x; set this.x = aralikdenetlex(value); private int y; public int Y get return this.y; set this.y = aralikdenetlex(value); 5

private static int aralikdenetlex(int x) if (x < 0 x > 1280) throw new ArgumentOutOfRangeException("X"); return x; private static int aralikdenetley(int y) if (y < 0 y > 1024) throw new ArgumentOutOfRangeException("Y"); return y; Aşağıdaki örnek bir Ekran Pozisyonu 2 yapısının X ve Y özelliklerindeki değerlerini okumayı gösterir. EkranPozisyonu2 orijin2 = new EkranPozisyonu2(0, 0); int xpoz = orijin2.x; //orijin.x.get'i çağırır int ypoz = orijin2.y; //orijin.x.get'i çağırır Özellik ve alanlara aynı söz dizimini kullanarak eriştiğinize dikkat ediniz. Bir özelliği okuma bağlamında kullandığınızda derleyici alan benzeri kodunuzu otomatik olarak o özelliğin get erişimcisine yapılan bir çağrıya dönüştürür. Benzer biçimde de bir özelliği yazma bağlamında kullanırsanız derleyici kodu otomatik olarak set erişimcisine yapılan bir çağrıya dönüştürür. Bir özelliği hem okuma hem de yazma bağlamında kullanmak da olasıdır. Örneğin;derleyici aşağıdaki gibi ifadeleri otomatik olarak hem get hem de set erişimcilerine yapılan çağrılara dönüştürür. orijin2.x += 10; 6

1.2.1. Sadece Okunabilir Sadece get erişimcisi olan özellikleri bildirmenize izin verilir. Bu durumda özelliği yalnızca okuma bağlamında kullanabilirsiniz. Aşağıdaki örnekte Ekran Pozisyonu 2 yapısının X özelliğinin sadece okunabilir bir özellik olarak bildirilmiş biçimini görebilirsiniz: struct EkranPozisyonu2... public int X get return this.x;... X özelliği bir set erişimcisi içermez. Bu yüzden X değişkenine değer atayarak bir yazma bağlamında kullanmak için yapılan her girişim başarısız olur. Örneğin; orijin2.x = 140; //derleme zamanı hatası 1.2.2. Sadece Yazılabilir Benzer biçimde yalnızca set erişimcisi olan bir özellik bildirebilirsiniz. Bu durumda özelliği yalnızca yazma bağlamında kullanabilirsiniz. Örneğin aşağıda Ekran Pozisyonu 2 yapısının X özelliğinin sadece yazılabilir bir özellik olarak bildirilmiş biçimini görebilirsiniz. struct EkranPozisyonu2... public int X set this.x = aralikdenetlex(value);... X özelliği bir get erişimcisi içermez. X i okuma bağlamında kullanmak için yapılan her girişim başarısız olur. Örneğin; Console.WriteLine(orijin2.X); orijin2.x = 200; orijin2.x += 10; // derleme zamanı hatası // derlenir // derleme zamanı hatası 7

ÖLÇME VE DEĞERLENDİRME ÖLÇME VE DEĞERLENDİRME Aşağıdaki soruları dikkatlice okuyunuz ve doğru seçeneği işaretleyiniz. 1. Kapsülleme kavramını aşağıdakilerden hangisi en iyi tanımlamaktadır? A) Alanları özel yapmak B) Yapı veya sınıfa alan değiştirme metodu eklemek C) Yapı veya sınıfa alan okuma metodu eklemek D) Yapı veya sınıftaki alanları özel yapıp değiştirme ve okumayı denetleme için metotlar kullanmak 2. Sadece okunabilir özellik eklemek için aşağıdakilerden hangi erişimci kullanılır? A) get B) set C) private D) public 3. Sadece yazılabilir özellik eklemek için aşağıdakilerden hangi erişimci kullanılır? A) get B) set C) private D) public 4. Bir özellik okuma ve değiştirme kullanımı bakımından aşağıdakilerden hangisine benzer? A) alan B) metot C) yapı D) sınıf DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise bir sonraki öğrenme faaliyetine geçiniz. 14

ÖĞRENME FAALİYETİ 2 AMAÇ ÖĞRENME FAALİYETİ 2 Bu faaliyetle gerekli araç, gereç ve ortam sağlandığında arayüz özelliklerini (interface properties) kullanabileceksiniz. ARAŞTIRMA Arayüzlerde özellikler nasıl tanımlanır? Araştırarak rapor hâlinde sınıfa sununuz. 2. ARAYÜZ ÖZELLİKLERİ Arayüzler yöntemlerin yanında özellikler de belirtebilir. Bunu yapmak için get ve/veya set anahtar sözcüğünü kullanırsınız. Ancak arayüzler uygulama kodları barındıramayacakları için get ve set erişimcilerinin gövdeleri yerine noktalı virgül (;) kullanılır. Örneğin; interface IEkranPozisyonu int X get; set; int Y get; set; Bu arayüzü kullanan tüm sınıf ve yapılar get ve set erişimci yöntemleri ile birlikte X ve Y özelliklerini de kullanmak zorundadır. Örneğin; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ArayuzOzellikleri struct EkranPozisyonu: IEkranPozisyonu int x, y; public int X get return x; set 15

x = value; public int Y get return y; set y = value; 2.1. Özellikleri Uygulamada Kullanma Nesne tabanlı programlama yazılımında Özellikler (Properties) penceresini kullandığınızda çeşitli uygulama bileşenlerinin [Metin Kutusu (TextBox), Düğme (Button) gibi bileşenler] özellik değerlerini ayarlayan alan bir kod oluşturursunuz. Bazı bileşenlerin çok sayıda özelliği vardır ve bazı özellikler diğerlerinden daha fazla kullanılır. Aşağıdaki örnekte gördüğünüz söz dizimini kullanarak bir çok özelliği çalışma zamanında değiştirebilirsiniz. Merkez adında bir Ekran Pozisyonu nesnesi yaratıp X özelliğini 0 a ayarlayan ve onu alıp ekrana yazan basit bir örnek aşağıdaki gibi olabilir:... static void Main(string[] args) EkranPozisyonu merkez = new EkranPozisyonu(); merkez.x = 0; Console.WriteLine(merkez.X);... 2.2. Otomatik Özellikler Özelliklerin başlıca amacı alanların kullanımını uygulamasını dış dünyadan saklamaktır. Özelliklerin amacına yönelik kullanımı önemlidir. Çünkü get ve set erişimciler, sadece alana bir değer atamak ya da değer okumak işlemlerini yerine getiriyorsa bunun doğru bir yaklaşım olup olmadığı sorusu akla gelebilir. Veriyi ortak (public) alanlar olarak göstermek yerine özellikler tanımlamanız için en az iki neden vardır: Uygulamalarla Uygunluk: Alanlar ve özellikler, derlemelerde farklı meta veri kullanarak kendilerini ortaya koyar. Bir sınıf geliştiriyorsanız ve ortak alanlar kullanmaya karar verdiyseniz bu sınıfı kullanan bir uygulama, alanlar olarak bu öğelere başvuracaktır. Bir özelliği okurken ve yazarken kullandığınız söz dizimini bir alanı okumak ve yazmak için kullanabilseniz de derlenen kod gerçekte çok farklıdır. Daha sonra bu alanları özellikler olarak değiştirmeye 16

karar verirseniz mevcut uygulamalar yeniden derlenmeden sınıfın güncellenmiş sürümünü kullanamaz. Uygulamayı bir şirketin çok sayıda kullanıcısına uyguladıysanız bu bir dezavantajdır. Arayüzlerle Uygunluk: Bir arayüz gerçekleştiriyorsanız ve arayüz özellik olarak bir öğe tanımlıyorsa özellik sadece özel (private) alanlardaki veriyi okuyor ve yazıyor olsa bile arayüzdeki şartlara uyan bir özellik yazmanız gerekir. Sadece aynı adla bir ortak alan göstermek yoluyla bir özellik geliştiremezsiniz. Programlama dili tasarımcıları, programcıların gereğinden fazla kod yazacak kadar zamanı olmayan meşgul insanlar olduklarını bilir. Bu amaçla derleyici sizin için otomatik özellikler kodunu üretebilir. class Daire public int YariCap get; set; Bu örnekte Daire sınıfı YariCap adında bir özellik içerir. Bu özellik, türü dışında herhangi bir bilgi içermez. Derleyici bu tanımı otomatik olarak aşağıda görüldüğü şekle dönüştürür. class Daire private int _yaricap; public int YariCap get return this._yaricap; set this._yaricap = value; 17

2.3. Özellikler İle Nesneleri Başlatma Bir nesneyi başlatmak için kurucuları tanımlamayı öğrenmiş olmalısınız. Bir nesne birden çok kurucuya sahip olabilir ve bir nesnedeki farklı öğeleri başlatmak için çeşitli parametrelerle kurucular tanımlayabilirsiniz. Ancak bu pratik bir yaklaşım değildir. Bir sınıfın kaç adet alan içerdiğine ve alanları başlatmak için istediğiniz çeşitli bileşimlere bağlı olarak çok sayıda kurucu yazmaya son verebilirsiniz. Bir sınıf oluşturulduğunda, set erişimcilere sahip ortak (public) özellikler için değerler belirleyerek bu oluşumu başlatabilirsiniz. Yani Ucgen adında bir sınıfın nesnelerini oluşturup bunları herhangi bir bileşimle belirleyebilirsiniz. Ucgen sınıfı aşağıdaki şekilde tanımlanmış olsun: class Ucgen private int kenar1uzunluk = 10; private int kenar2uzunluk = 10; private int kenar3uzunluk = 10; public int Kenar1Uzunluk set this.kenar1uzunluk = value; public int Kenar2Uzunluk set this.kenar2uzunluk = value; public int Kenar3Uzunluk set this.kenar3uzunluk = value; Bu sınıfa ait özellik ile nesne başlatma bileşimleri aşağıda görüldüğü gibi olabilir: 1. Ucgen ucgen1 = new Ucgen Kenar1Uzunluk = 20 ; 2. Ucgen ucgen2 = new Ucgen Kenar1Uzunluk = 20, Kenar2Uzunluk = 15 ; 3. Ucgen ucgen3 = new Ucgen Kenar1Uzunluk = 20, Kenar2Uzunluk = 15, Kenar3Uzunluk = 10 ; 1. örnekte ucgen1 nesnesi oluşturulurken sadece Kenar1Uzunluk özelliğine 20 değeri verilmiş diğer iki özellik ayarlanmamıştır (Kenar2Uzunluk ve Kenar3Uzunluk). Diğer özelliklere biz değer vermediğimiz için oluşturulan ucgen1 nesnesinin alanlarının değerleri aşağıdaki gibi olacaktır: kenar1uzunluk - 20 kenar2uzunluk - 10 kenar3uzunluk - 10 18

2. örnekte nesne oluşturulurken Ucgen sınıfında yer alan kenar1uzunluk 20, kenar2uzunluk 15 olarak belirtildiğinden, kenar3uzunluk sınıf içerisinde ayarlandığı hâliyle yani 10 olarak kalacaktır. 3. örnekte tüm uzunluklar özellikler yardımıyla ayarlandığı için tüm uzunluklarımız verilen değerlerle ayarlanacaktır. 19

ÖLÇME VE DEĞERLENDİRME ÖLÇME VE DEĞERLENDİRME Aşağıdaki soruları dikkatlice okuyunuz ve doğru seçeneği işaretleyiniz. 1. Bir arayüzde özelliğin set ve get erişimcisinin gövdesi yerine aşağıdaki işaretlerden hangisi konur? A) : B). C) ; D), 2. Özellikler ile nesneleri başlatırken özellikleri aşağıdaki hangi işaret içine yazmak gerekir? A) Köşeli parantezler B) Tırnak işaretleri C) Normal parantezler D) Küme parantezleri 3. Bir kısmı programcı tarafından yazılınca derleyici tarafından otomatik olarak tamamlanan öğe aşağıdakilerden hangisidir? A) Arayüz B) Sınıf C) Otomatik özellik D) Yapı DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise Modül Değerlendirme ye geçiniz. 26

MODÜL DEĞERLENDİRME MODÜL DEĞERLENDİRME Aşağıdaki cümlelerin başında boş bırakılan parantezlere, cümlelerde verilen bilgiler doğru ise D, yanlış ise Y yazınız. 1. ( ) Özellikler bir sınıf ve/veya yapıdaki alanları gizlemek için kullanılır. 2. ( ) Alanları gizlemeye kapsülleme denir. 3. ( ) Ortak (public) veri kullanmanın dezavantajı, derleyicinin buna izin vermemesidir. 4. ( ) Özelliklerin kullanımı metotların kullanımına çok benzemektedir. 5. ( ) Sadece okuma amaçlı bir özellik oluşturulabilinir. 6. ( ) Sadece yazma amaçlı bir özellik isteniyorsa özelliğin tanımında set erişimcisi kullanılmalıdır. 7. ( ) Arayüzler özellik tanımı içeremez. 8. ( ) Özellikler uygulamada aynen bir değişken gibi kullanılır. 9. ( ) Özellik ayrıntılarının derleyici tarafından yazılmasına otomatik özellik denir. 10. ( ) Gerekirse özellikler kullanılarak nesneler başlatılabilinir. DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise bir sonraki modüle geçmek için öğretmeninize başvurunuz. 27

ÖĞRENME FAALİYETİ 1 AMAÇ ÖĞRENME FAALİYETİ-1 Temsilcileri sınıf içinde uygun şekilde tanımlayıp kullanabileceksiniz. ARAŞTIRMA Bu faaliyet öncesinde yapmanız gereken öncelikli araştırmalar şunlardır. Metod imzası nedir? Tanımlanmasındaki amaçları araştırınız. Arayüz (Interface) kullanımının programınıza kattığı kullanım esnekliğini ve avantajlarını araştırınız (Sınıfta tartışınız.). Derleme zamanı ve çalışma zamanı kavramlarını araştırınız. 1. TEMSİLCİLER Program içerisinde bir veya daha fazla metodu gösteren (işaret eden), referans türünden nesnelere temsilci (delegate) adı verilir. Başka bir deyişle metotların referansını tutan türler olarak da tanımlayabilirsiniz. Temsilcinin kelime anlamı aracılık yapan dır. Temsilci.NET için bir metoda aracılık yapmaktadır. Referans bilgisi, nesnenin bellekteki yerini gösteren bir adres değişkenidir. Alt düzeyli dillerde bu değişken işaretçi (pointer) olarak da bilinir. Temsilcinin taşıdığı referans bilgisi nesneyi değil, bir metodun bellekte oluşturulduğu yerin başlangıç adresini işaret eder. Söz konusu metodu, temsilci vasıtasıyla referansı üzerinden çalışma zamanında görevini yerine getirmek üzere çağırabiliriz. İlk bakışta programınız içinde metodu direkt olarak çağırmak yerine, neden temsilci kullanma gereği duyulduğunu düşünebilirsiniz. Bu sorunun cevabı için aşağıdaki şekilleri inceleyiniz. Resim 1.1: Temsilci kullanılmadan yapılmış metod çağrımları 3

Resim 1.2: Temsilci vasıtasıyla yapılmış metod çağrımları Aslında buradaki kritik kelimenin derleme zamanı değil çalışma zamanı olduğunu söyleyebiliriz. Program yazımı aşamanızda belirlediğiniz bir metodu ne zaman çağırmanız gerektiğine rahatlıkla karar verebilir, kodunuz içinde sorunsuzca çağrımı yapabilirsiniz. Bütün bu süreci derleme aşamasında düşündüğünüz anlamına gelir. Bu kullanım resim 1.1 de gösterilmiştir. Ancak bazı senaryolarda hangi metodun işletileceği kararı, programınızın çalışma zamanında ele alınmasını gerektirebilir. Bir temsilci tanımlaması ile derleme zamanı için bir metodun çalıştırılacağı bilgisini programınıza vermiş olursunuz. İşaret edeceği metodu çalışma zamanında belirleyebilir ve dinamik olarak değiştirebilirsiniz. Temsilciler neden kullanılır Bir temsilci ile sadece bir tek metodu işaret edebileceğiniz gibi, birden fazla metot için tanımlanmış ve oluşturulmuş temsilcileri de kullanabilirsiniz. Bir temsilcinin tanımlanması, onu kullanmak için yeterli değildir elbette. Her şeyden önce bir amacınız olmalıdır. Bir temsilciyi çalışma zamanında oluşturabilir ve kullanabilirsiniz. Diğer yandan, tek bir temsilcide birden fazla temsilciyi toplayarak bu temsilcilerin işaret ettiği, tüm metotları tek bir seferde çalıştırma lüksüne de sahipsiniz. Ancak temsilciler gerçek anlamda iki amaçla kullanılırlar. Bunlardan birincisi olaylardır (events). Olaylar.NET için tıpkı temsilciler gibi temel kavramların arasında yer alır. Temsilciler olayların desteklenmesinde önemli bir rol oynar. Diğer yandan, bir metodun çalışma zamanında, hangi metotların çalıştırılacağına karar vermesi gerektiği durumlarda kullanılır. Elbette söz konusu bu amaçları, herhangi bir temsilciye ihtiyaç duymadan da gerçekleştirebiliriz. Ancak temsilcileri kullanmadığınızda, size sağladığı üstün programlama tekniği, kullanım kolaylığı ve artan verimliliği de göz ardı etmiş olursunuz. 4

1.1. Temsilcileri (Delegates) Tanımlama C# programlama dilinde metotların referansını tutan özel bir tip geliştirilmiştir. Bu tip delegate anahtar kelimesi ile tanımlanır. Yazım kuralı erişim_belirteci delegate metodun_geri_dönüş_tipi temsilci_adı (Parametre_listesi) Yazım kuralı dikkatlice incelendiğinde bir temsilci tanımlamasının metot yazım formuna olan benzerliği dikkatinizi çekebilir. Tek fark öncesinde delegate anahtar kelimesinin kullanılmasıdır. Her veri tipinde olduğu gibi temsilcide bir erişim belirtecine (private, protected vb.) sahiptir. Geri dönüş tipi temsilcinin işaret etmek istediği metotların döndürdüğü değerin tipidir. Parametreler, temsil edilen metodun almak isteyebileceği parametre listesidir. Tanımlama aşamasında dikkat edilmesi gereken temsilci nesneleri ile göstermek yani işaret etmek istediğimiz metotlar temsilcinin imzasına sahip olmalıdır. Bildiğiniz gibi metot imzaları, metodun geri dönüş tipi ve aldığı parametreler ile belirlenmektedir. Örnek 1.1. public delegate int toplamtemsilcim(int x, int y); Yukarıda iki parametreli ve parametre tipleri ile geri dönüş tipi tamsayı olan toplamtemsilcim isimli bir temsilci tanımlaması yapılmıştır. Örnek 1.2. private delegate void getirtemsilcim(string kelime); Yukarıda geri dönüş değeri olmayan, string türünden tek parametreli getirtemsilcim isimli bir temsilci tanımlaması yapılmıştır. Örnek 1.3. private delegate string edithandler(params string[] liste); Yukarıda geri dönüş değeri string olan ve string türünden değişken sayıda parametre alan edithandler isimli bir temsilci tanımlaması yapılmıştır. Temsilciler aslında bir metot tanımlarlar fakat bunu uygulamazlar. İşte bu özellikleri ile arayüzlerdeki metot tanılamalarına benzerler. 5

1.2. Temsilcileri Kullanma Programlarınızda temsilciler kullanmak istediğinizde, öncelikle bu temsilcinin tanımı yapılır. Bir temsilci tanımlandığında, aslında işaret edebileceği metotların imzalarını da belirlemiş olur. Dolayısıyla, bir temsilci sadece tanımladığı metot imzasına uygun metotlar için kullanılabilir. Temsilci tanımları tasarım zamanında yapılır. Bir temsilciyi, bir metodu işaret etmesi için kullanmak istediğimizde ise, çalışma zamanında onu new yapılandırıcısı ile oluşturur ve işaret etmesini istediğimiz metodu ona parametre olarak veririz. Temsilci kullanımı 3 aşamada yapılır. 1. Tanımlama (Declare). 2. Örneklenme (Instance) 3. Çağırma (Invoke) Tanımlama aşaması : Temsilci referans alacağı metotların imzalarına uygun şekilde delegate anahtarı ile tanımlanır. Örnekleme : Tanımlaması yapılan temsilci artık bir veri türü olarak kabul edilebilir. Temsilci adı üzerinden new anahtarı kelimesi ile örneklemesi yapılır. Çağırma : Temsilciyi çağırma işlemi metod çağrımından farksızdır. Temsilci imzasına uygun şekilde parametreleri verilir, geri dönüş türüne uygun bir nesneye, dönen değeri aktarılabilir. Resim 1.3: Temsilerin kullanım süreçleri 6

Temsilci kullanım süreçlerinin bir kısmı derleyici tarafından derleme zamanında, bir kısmı işletim sistemi tarfından çalışma zamanında ele alınır. Resim 1.2.1 de kullanım süreçlerinin hangi zamanlarda işletildiğini göstermektedir. Örnek 1.4. Temsilcilerin bir program içinde nasıl ele alındıklarını ve bir metodu nasıl çalıştırdıkları görülmektedir. namespace DelegateTest1 class Program // Tanımlama (Declaration) public delegate void TestHandler(); public static void Metod1() Console.WriteLine("Temsilci ile çağırıldım..."); static void Main(string[] args) // Örnekleme (Instantiation) TestHandler test = new TestHandler(Metod1); // Çağırma (Invocation) test(); Yukarıdaki program kodu temsilcilerin kullanım aşamalarına göre incelendiğinde; 1-Tanımlama aşaması: public delegate void TestHandler(); Hiçbir parametresi ve geri dönüş değeri olmayan metotları işaret edecek TestHandler adında temsilci tanımlaması (declaration) yapılır. 2-Örneklenme aşaması: TestHandler test = new TestHandler(Metod1); Main() bloğu altında ilk olarak TestHandler tipinde test adında bir nesne new yapılandırıcısı ile örneklenir. Örnekleme (Instance) aşamasında nesnenin Metod1 isimli yöntemi işaret edeceği belirtilir. 7

3-Çağırma aşaması: test(); Son olarak test isimli temsilci işaret ettiği metodu çalıştırmak üzere çağırımı (Invoke) yapılmıştır. Program çalıştırıldığında oluşan ekran çıktısı Resim 1.4 teki gibi olacaktır. namespace DelegateTest2 class Program public static int Topla(int x, int y) return x + y; public static int Fark(int x, int y) return x - y; Resim 1.4: Program kodu ekran çıktısı Örnek 1.5. Aşağıdaki örnek programımızda Topla ve Fark adında iki farklı metodun tek bir temsilci üzerinden ayrı zamanlarda çalıştırılmaktadır. // Tanımlama private delegate int Temsilcim(int sayi1, int sayi2); static void Main(string[] args) // Temsilci örneklemesi Topla() metodunu işaret eder. Temsilcim istemsil = new Temsilcim(Topla); // Temsilci örneklemesi üzerinden metodun çağırılması int toplamsonuc = istemsil (8, 5); Console.WriteLine("Sonuc :0", toplamsonuc); // Temsilci örneklemesi Fark() metodunu işaret etmektedir t = Fark; // Temsilci örneklemesi üzerinden metodun çağırılması int farksonuc = istemsil (8, 5); Console.WriteLine("Sonuc :0", farksonuc); Console.ReadLine(); 8

Yukarıdaki örneğimizde Topla ve Fark metotlarını referans alacak Temsilcim adında tek bir temsilci tanımlaması yapılmıştır. Yazım kuralı gereği tanımlama aşamasında temsilcimizin çalışma anında çağıracağı metotlar ile aynı imzaya sahip olduğuna dikkat ediniz. Bu durum resim 1.5 te gösterilmiştir. Resim 1.5: Temsilci ve metot imzaları Metot imzası ile temsilci imzası arasında uyuşmazlık halinde.' has the wrong return type şeklinde bir derleme zamanı hatası alabilirsiniz. Kodlama sürecinde örneklemeyi yazarken Resim 1.6 daki görüntü dikkatinizi çekmiştir. Resim 1.6: Temsilci örneklemesine ait yapılandırıcı parametreleri Temsilcim tipindeki t nesnesi new anahtarı ile oluşturulurken temsilcinin sahip olduğu imza türünden bir metot talepte bulunduğu dikkate alınmalıdır. Çağırma aşamasında sonuç değişkenlerimize; int toplamsonuc = istemsil (8, 5); // Sonuc : 13 int farksonuc = istemsil (8, 5); // Sonuc :3 şeklinde aynı atamalar yapılmış olmasına karşın çalışma zamanında farklı değerlerin üretildiği görülmektedir. Bunun sebebi farksonuc değişkenine temsilciden dönen değer verilmeden önce t = Fark; satırı ile temsilcimiz artık Topla metodu yerine Fark metodunu referans alması ve çalıştırmasıdır. Örnek 1.6. Bir önceki örnekte bulunan Topla ve Fark metotlarımızı ayrı bir sınıf altında toplayalım. Metot çağrımlarını temsilci üzerinden gerçekleştirelim. Öncelikle TestClass isimli bir sınıf oluşturunuz ve söz konusu metotları yazınız. 9

namespace DelegateTest3 class TestClass public int Topla(int x, int y) return x + y; public int Fark(int x, int y) return x - y; Sırada TestClass sınıfını kullanacak program kodlarını yazınız. namespace DelegateTest3 class Program private delegate int Temsilcim(int sayi1, int sayi2); static void Main(string[] args) // TestClass sınıfından test nesnesinin örneklenmesi TestClass test = new TestClass(); // Temsilci örneklemesi üzerinden metodun çağırılması Temsilcim t = new Temsilcim(test.Topla); // Temsilci üzerinden metodun çalıştırılması int toplamsonuc = t(8, 5); Console.WriteLine("Sonuc :0", toplamsonuc); // Temsilci Fark() metodunu işaret etmektedir t = test.fark; // İşaret edilen metodun çalıştırılması int farksonuc = t(8, 5); Console.WriteLine("Sonuc :0", farksonuc); 10

TestClass sınıfına ait Topla ve Fark metotlarının kullanımı için sınıfa ait nesne örneğine ihtiyaç duyar. Bir temsilci, kendisiyle ilişkili, statik, statik olmayan veya başka bir sınıf örneğinden gelen yeni bir metotla kullanılabilir. Referans türleri aynı zamanda null değerler taşıyabilir. Temsilcim t = new Temsilcim(test.Topla); t=null; // Geçerli int sonuç = t(8,5); // Temsilci null olduktan sonra geçersiz Yukarıda bulunan kod örneğinde Temsilcim tipindeki t nesnesine null değer ataması yapılmıştır. Null değer taşıyan temsilci, herhangi bir metodu işaret etmez. Bu durumda olan temsilcinin çağırılması çalışma zamanında Object reference not set to an instance of an object. hatasını verecektir. Şimdiye kadar yaptığınız örneklerde temsilcinin tek bir metodu referans aldığını gördünüz. Bu tip kullanım şekline Single-Cast (Tekli Çağrı) adı verilir. Ancak programlarımızda bazen, tek bir temsilciye birden fazla temsilci ekleyerek, birden fazla metodu tek bir temsilci ile çalıştırmak isteyebiliriz. Bu durumda Multi-Cast (Çoklu Çağrı) temsilciler tanımlarız. Çoklu çağrı kullanım şeklinde yapmanız gereken metot eklemek ise += metot çıkarmak ise -= operatörlerini kullanmaktır. Temsilci çağrımı yapıldığında kendi referans listesinde tuttuğu tüm metotların çağrımını sırayla gerçekleştirecektir. Örnek 1.7. Çoklu çağrı için temsilciler üzerinde += ve -= operatörlerinin kullanımı aşağıda gösterilmiştir. namespace MultiCastDelegate class Program static void Metod1() Console.WriteLine("Metod1 çalışıyor..."); static void Metod2() Console.WriteLine("Metod2 çalışıyor..."); static void Metod3() Console.WriteLine("Metod3 çalışıyor..."); 11

private delegate void Temsilcim(); static void Main(string[] args) Temsilcim t = new Temsilcim(Metod1); t(); // Temsilci Metod1'i referans alır. Console.WriteLine("********************"); t += Metod2; // Temsilci listesine Metod2 eklenmektedir. t += Metod3; // Temsilci listesine Metod3 eklenmektedir. t(); // Temsilci Metod1+Metod2+Metod3 çağırır. Console.WriteLine("********************"); t -= Metod2; // Temsilci listesinden Metod2 çıkarılmaktadır. t(); // Temsilci Metod1+Metod3 çağırır. Console.WriteLine("********************"); t -= Metod1; // Temsilci listesinden Metod1 çıkarılmaktadır. t(); // Temsilci yalnızca Metod3'i çağırır. Console.ReadLine(); Örneğe ait program kodu çalıştırıldığında resim 1.7 de görülen ekran çıktısını verecektir. Resim 1.7: Program testi sonucu Örnek 1.8. Bir otomasyon projesi için bir cihazın aç / kapa işlemini tek fonksiyonla gerçekleştirme ihtiyacımız bulunmaktadır. Bu fonksiyonu kodlayınız. namespace DelegateTest4 public class Cihaz private delegate void Temsilcim(); Temsilcim faaliyet; 12

public Cihaz() // Kurucu metod altında temsilci Ac metoduna işaret ediyor. faaliyet=new Temsilcim(Ac); private void Ac() //Cihaz açılmasının ardından temsilci Kapat metodunu işaret ediyor. Console.WriteLine("Cihaz Açıldı.."); faaliyet=kapat; private void Kapat() // Cihaz kapatılmasının ardından temsilci Ac metodunu işaret ediyor. Console.WriteLine("Cihaz Kapatıldı.."); faaliyet=ac; public void Kontrol() //Sadece kontrol metodu temsilciyi çağırabilir. faaliyet(); Cihaz sınıfımız içinde bulunan Ac ve Kapat metodları private erişim belirtecine sahiptir. Sınıfa özgü bu iki metodu Kontrol adında bir metod harekete geçirecektir. Bunun için faaliyet temsilcisi kurucu metod altında örneklenmekte ve Kontrol metodu altında çağrılmaktadır. Cihaz açık konumda iken temsilci Kapat metodunu, kapalı konumda iken Ac metodunu işaret etmektedir. Sınıfımızı test etmek için aşağıdaki kodları yazınız ve çalışmasını izleyiniz. namespace DelegateTest4 class Program static void Main(string[] args) Cihaz ch=new Cihaz(); for(int j=0;j<=7;j++) // Cihazın kontrol fonksiyonu çağrılıyor. ch.kontrol(); Console.ReadLine(); 13

Resim 1.8: Program testi sonucu Temsilciler (delegates) çok kanallı programlamada (multi threading), asenkron (asynchronous) mimarilerde (Polling, Callback, WaitHandle gibi) ve son olarak olay tabanlı (event based) kodlamada kullanılmaktadır. Modülünüzün sunduğu bilgiler ışığında söz konusu kullanım alanlarında temsilcilerin oynadığı rolü, programlama tekniklerini, ve sunduğu avantajları derinlemesine incelemeniz sizi daha ileriye taşıyacaktır. 14

ÖLÇME VE DEĞERLENDİRME ÖLÇME VE DEĞERLENDİRME Aşağıdaki cümlelerde boş bırakılan yerlere doğru sözcükleri yazınız. 1. Temsilciler... referansını gösteren türlerdir. 2. Referans bilgisi nesnenin bellekteki. değişkenidir. 3. Temsilcileri kullanmadan yapılan metot çağrımları zamanında gerçekleşir. 4. Temsilciler kullanılarak yapılan metot çağrımları. zamanında gerçekleşir. 5. Bir temsilci anahtar kelimesi ile tanımlanır. DEĞERLENDİRME Cevaplarınızı cevap anahtarıyla karşılaştırınız. Yanlış cevap verdiğiniz ya da cevap verirken tereddüt ettiğiniz sorularla ilgili konuları faaliyete geri dönerek tekrarlayınız. Cevaplarınızın tümü doğru ise bir sonraki öğrenme faaliyetine geçiniz. 16

ÖĞRENME FAALİYETİ 2 AMAÇ ÖĞRENME FAALİYETİ-2 Olayları sınıf içinde uygun şekilde tanımlayıp kullanabileceksiniz. ARAŞTIRMA Temsilcilerin program akışını değiştirmede oynadığı rolü araştırınız. 2. OLAYLAR Varlıklar doğaları gereği kendileri ile ilgili oluşan durumları olay olarak algılar. Olay meydana geldiğinde bunu bildirmek isteyebilir. Bunu diğer varlıklarla etkileşime geçerek veya kendi varlıklarında başka bir davranışı tetikleyerek sağlar. Neticede programlarımız içindeki nesnelerimizin gerçeklikteki varlıklara karşılık geldiğini düşünecek olursanız olayların ve buna bağlı bildirimlerin de sınıflarımız tarafından işlenebilmesi mümkün olmalıdır. Olaylar (event) sınıfın (class) içinde oluşan bir durumun meydana geldiğini bildiren otomatik bildirgelerdir..net Framework te olaylar önemli faaliyetleri yakalamanıza ve durumu işlemek için temsilcisi ile birlikte sınıflarınıza destek verir. Olayların sınıflarınız içinde ele alınması 3 aşamadan meydana gelmektedir. Olay tanımlama Olaya abone olma Olayı çağırma 2.1. Olay (Event) Tanımlama Olaylar bir sınıfın üyesi olup event anahtar kelimesi ile tanımlanırlar. Yazım kuralı; erişim_belirteci event olay_temsilcisi olay_adı Olay onun çalışmasını destekleyecek bir temsilci ile birlikte tanımlanmaktadır. Söz konusu temsilcimiz olay meydana geldiğinde temsilcisinin işaret ettiği metodu çağırarak bildirimde bulunurlar. Bir olayın (event) tanımlanabilmesi için mutlaka bir temsilci tipi ile eşleştirilmesi gerekmektedir. 17

Örnek 2.1: Ürün sınıfında stok tükenmesi olay tanımlamasına ait örnektir. class Urun private delegate void StokTemsilcisi(); public event StokTemsilcisi StokBitti;... İlk satırda olayın işlenmesini sağlayacak temsilcinin tanımlaması yapılmıştır. StokTemsilci geri dönüş tipi ve parametresi olmayan bir metodu referans alabilecek şekilde düzenlenmiştir. Ardından temsilcisi ile birlikte çalışacak olan StokBitti olayının tanımlaması yapılmıştır. Programlarınız için de kullanmak istediğiniz sınıflarınızda bu türden kodlama ile rahatlıkla olay tanımlamalarını gerçekleştirebilirsiniz. 2.2. Olaya Abone Olma Aslında bir olayın tetiklenmesi, bir istisna (exception) nesne örneğinin ortama fırlatılmasına (throw) benzetilebilir. Tek fark ortama fırlatılan istisnaların catch blokları ile yakalanabiliyor olmasıdır. Olaylarda durum farklıdır. Ortada bir catch bloku yoktur. Bunun yerine bir abone (subscriber) vardır. Basit olarak olayın tetiklenmesi sonucu çalıştırılacak olay metodunun bulunduğu nesne örneğini abone olarak düşünebiliriz. Bir başka deyişle olayı yakalayıp değerlendirecek olan nesne, olayın sahibi olan nesnenin ilgili olayına (event) abone olmaktadır. Bu durum resim 2.1 de görebilirsiniz. Dolayısıyla olayı tanımlayan ve tetikleyen nesneyi yayımcı (publisher) olarak da düşünebilirsiniz. 18

public class Urun public delegate void StokTemsilcisi(); public event StokTemsilcisi StokAzaldi; class Program Resim 2.1: Olay metodunun yayımcı nesneye abone olması Burada söz konusu olan abone etme işlemi aslında olayın (event) += operatörü yardımıyla program nesne örneği içerisinde yüklenmesidir. Olaylar tanımlanırken hep bir temsilci (delegate) tipi yardımıyla oluşturulurlar. Dolayısıyla abone olan sınıf içerisinde yayımcı sınıf nesnesi için ilgili olay += operatör ile yüklendiğinde, temsilciye (delegate) parametre olarak verilen metot referansı yayımcı nesnesine bildirilir. Böylece yayımcı nesne örneği içerisinde ilgili olay tetiklendiğinde program içinde hangi metodun çağrılacağı bilinmektedir. Örnek 2.2. StokAzaldı isimli olayın abone sınıf tarafından olay metoduna bağlayan program örneğidir. static void Main(string[] args) // Urun sınıfından kitap nesnesinin örneklenmesi Urun Kitap = new Urun(); // Kitap nesnesine dair stok azalması meydana geldiğinde // Kitap_StokAzaldi() isimli olay metodunun temsilciye referans edilmesi Kitap.StokAzaldi += new Urun.StokTemsilcisi(Kitap_StokAzaldi); static void Kitap_StokAzaldi() // Olay meydana geldiğince 19 çalışacak olan metod

Temsilcilerin çoklu çağrıyı (multicasting) desteklediğini düşünürseniz bir tek olaya dilediğiniz kadar olay metodu bildirebilirsiniz. Örnek 2.3. Kitap nesnemiz stoklarda tükenme noktasına geldiğinde tedarikçimize sipariş verilmesi, mail gönderilmesi ve rapor yazması istenmektedir., class Program static void Main(string[] args) Urun Kitap = new Urun(); Kitap.StokAzaldi += new Urun.StokTemsilcisi(Siparis_Ver); Kitap.StokAzaldi += new Urun.StokTemsilcisi(Mail_Gonder); Kitap.StokAzaldi += new Urun.StokTemsilcisi(Rapor_Yaz); static void Siparis_Ver() // Sipariş kayıtlarına geçilecek... static void Mail_Gonder() // Tedarikçiye mail gönderilecek... static void Rapor_Yaz() // Rapor yazdırılacak... 2.3. Abonelik İptali Olay aboneliğini iptal etmek, temsilciyi bağlandığı olay metodundan ayırmak anlamına gelir. Temsilciler ünitesinden hatırlayacağınız üzere -= operatörü ile daha önce abone edilmiş olay metodunuzu temsilcinin referans listesinden kaldırabilirsiniz. 2.4. Olay Çağırma Olayları çağırmak temsilcileri çağırmaktan farksızdır. Çağrımı yaptığınız zaman olay tanımına ilişkilendirilmiş temsilci üzerinden abone olan tüm metotlar sırayla çağrılır. Burada dikkat edilmesi gereken husus, çağrım yapılmadan önce olay temsilcisinin herhangi bir olay metodunu işaret ettiğinden emin olmaktır. Temsilcilerin herhangi bir metodu işaret etmediklerinde null değere sahip olduğunu unutmayınız. Aksi halde çalışma zamanında 20

NullReferenceException hatası alırsınız. Olay çağrımından önce null değer karşılaştırmasının yapılması gerekmektedir. if (StokAzaldi!= null) // Olay Temsilcisi boş değilse... StokAzaldi(); // Olayı çağır. Olayın tetiklenmesi yalnızca olay tanımının yapıldığı sınıf içinde gerçekleştirilebilir. Örnek 2.4. Stok ambarlarında tutulan ürünlerin hareketlerini takip edecek bir proje geliştirmeniz istenmektedir. Buna göre herhangi bir ürünün stok miktarının belirli bir değerin altına düşmesi sonrasında kullanıcınıza uyarı verecek şekilde tasarlanacaktır. Programı konsol ortamında gerçekleştiriniz. Konsol uygulamanız içerisinde yer alan program sınıfınız abone (subscriber) olacak. Ürün sınıfı içerisinde tanımlayacağımız olay (event), stoktaki ürün sayısı 10 değerinin altına düştüğünde tetiklenecek şekilde tasarlanacaktır. Bir olay tanımlanırken mutlaka bir temsilcinin olması gerektiğinden bahsetmiştik. Dolayısıyla bir de temsilci (delegate) tipi geliştirmemiz gerekecektir. Söz konusu temsilci tipini ve Ürün sınıfını aşağıdaki gibi tasarlayabilirsiniz. namespace StokTakip public class Urun // Parametresi ve geri dönüş tipi olmayan olay temsilcisinin tanımlanması public delegate void StokAzaldiEventHandler(); // Olay temsilcisi üzerinden event tanımlanması public event StokAzaldiEventHandler StokAzaldi; 21

private int _id; public int Id get return _id; set _id = value; private string _ad; public string Ad get return _ad; set _ad = value; private double _birimfiyat; public double BirimFiyat get return _birimfiyat; set _birimfiyat = value; private int _stokmiktari; public int StokMiktari get return _stokmiktari; set _stokmiktari = value; if (value < 10 && StokAzaldi!= null) // StokMiktarı 10'dan küçükse ve StokAzaldı olayına bağlı temsilci null // değer içermiyorsa StokAzaldı olayını çağır StokAzaldi(); public Urun(int id, string adi, double fiyati, int stoksayisi) // Kurucu metod (Constructor) Id = id; Ad = adi; BirimFiyat = fiyati; StokMiktari = stoksayisi; public override string ToString() //.ToString metoduna ait görev tanımının yeniden yapılması return this.ad+" için stok miktarı "+this.stokmiktari.tostring(); 22

İlk olarak StokAzaldiHandler tipinden bir temsilci (delegate) tanımlıyoruz..net içerisinde var olan isimlendirme standartlarına göre niteliklere ait sınıf adlarının Attribute kelimesi ile, istisna (exception) tiplerinin Exception kelimesi ile, özellikle olaylar ile ilişkili temsilcilerinde çoğunlukla EventHandler kelimesi ile bittiğini görürsünüz. Bu nedenle olay ile ilişkili temsilcimizi StokAzaldiEventHandler olarak isimlendirdik. StokAzaldiEventHandler isimli temsilci tipi, geriye değer döndürmeyen ve parametre almayan metotları işaret edebilecek şekilde tasarlanmıştır. public delegate void StokAzaldiEventHandler(); Ardından UrunAzaldi isimli bir olay (event) tanımlanmıştır. public event StokAzaldiEventHandler StokAzaldi; Dikkat edilecek olursa event anahtar kelimesinden sonra StokAzaldiEventHandler isimli temsilci tipi gelmektedir. Son olarak da olayın adı yer alır. Böylece söz konusu olay için çalıştırılabilecek olay metotlarının yapısını StokAzaldiEventHandler isimli temsilcinin işaret edeceği belirtilmiş olur. Sırada, ilgili olay metodun nasıl ve nerede tetikleneceğinin belirlenmesi gerekmektedir. Bunun için StokMiktari isimli özelliğin set bloğunda aşağıdaki kod parçası kullanılmıştır. public int StokMiktari get return _stokmiktari; set _stokmiktari = value; if (value < 10 && StokAzaldi!= null) StokAzaldi(); Burada stok miktarı eğer 10 rakamının altındaysa ve StokAzaldi olayı null değere eşit değilse StokAzaldi isimli bir metot çağrısı yapılmaktadır. StokAzaldi olayının null olmaması bir şekilde += operatörü ile yüklendiği anlamına gelmektedir. Yani başka bir nesne bu olaya kendisini abone (subscribe to) etmiştir. Bu durumda söz konusu olay metodunun buradaki set bloku içerisinden çağırılması gerekir. Bu iş için yine olayı sanki bir metot gibi çağırmak yeterli olacaktır. Projemiz gereği ürün nesnelerimizi tüketecek olan program sınıfını aşağıdaki gibi tasarlayabilirsiniz. 23

namespace StokTakip class Program static void Main(string[] args) // Urun sınıfından dvd nesnesinin örneklenmesidir. Urun dvd = new Urun(10001, "DVD", 1.20, 0); // Stoklarda bulunan dvd azaldığında çalışacak olayın metoda bağlanır. dvd.stokazaldi += new Urun.StokAzaldiEventHandler(dvd_StokAzaldi); while (true) Console.WriteLine("1. Stok Girişi"); Console.WriteLine("2. Stok Çıkışı"); Console.Write ("Seçiminiz?(1-2-3)"); int secim = Convert.ToInt32(Console.ReadLine()); if (secim == 1) // Stoğumuza urun girişi yapılmak istenmesi durumunda // urun miktarını verilen sayıda arttırma işlemidir. Console.WriteLine("Stok Girişi Yapılacak Miktarı Giriniz:"); int miktar = Convert.ToInt32(Console.ReadLine()); dvd.stokmiktari += miktar; Console.WriteLine(dvd.ToString());// Urun hakkında bilgi verir. else if (secim == 2) // Stoğumuzdan urun tüketimi yapılmak istenmesi durumunda // urun miktarını verilen sayıda azaltma işlemidir. Console.Write("Stok Çıkışı Yapılacak Miktarı Giriniz:"); int miktar = Convert.ToInt32(Console.ReadLine()); dvd.stokmiktari -= miktar; Console.Write(dvd.ToString());// Urun hakkında bilgi verir. else if (secim == 3) // Programın çıkış seçeneğidir. break; static void dvd_stokazaldi() // Stok kritik seviyenin altına düştüğünde // olayın çalıştıracağı metod gövdesidir. Console.WriteLine("Uyarı!!! Stoklarımız kritik seviyenin altında..."); 24

Main metodu içerisinde Urun sınıfına ait bir nesne örneklendikten sonra StokAzaldi isimli olay, += operatörü ile yüklenmektedir. Burada Visual Studio kullanılıyorsa += işaretinden sonra iki kez tab tuşuna basmak yeterli olacaktır. Bu durumda Visual Studio otomatik olarak bir olay metodu oluşturacaktır. Örneğimizde bu olay metodu dvd_stokazaldi adıyla anılmaktadır. Program çalıştırıldıktan sonra girilen örnek veriler sonucu oluşan çıktı ekranı Resim 2.2 de gösterilmiştir. Resim 2.2: Stok takip programı ekran çıktısı Olay metodu içerisinde bir de ürünün o anki miktarının ne olduğunu öğrenebilmek veya birden fazla ürün nesne örneğini aynı olay metoduna bağlayacaksa (ki bu mümkündür), olay metodu içerisinde hangi Urun nesne örneğinin ilgili olayın sahibi olduğunu tespit edebilmek isteyebilirsiniz. İşte bu gibi gereksinime benzer ihtiyaçlar,.net içerisinde var olan tüm olaylar için de geçerlidir. O nedenle önceden tanımlanmış olan tüm olaylar aslında standart olarak iki parametre almaktadır. İlk parametre olayı tetikleyen nesne örneğine ait referansın yakalanması için kullanılırken, ikinci parametre olay metodu içerisine bilgi aktarmak maksadıyla ele alınır. Bu standart bir olay temsilcisinin işaret edeceği metodun parametrik yapısıdır. Tahmin edeceğiniz gibi ilk parametre object tipindendir. İkinci parametre ise genellikle EventArgs gibi kelimeler ile biten özel bir sınıftır. Kendi örneğimizi göz önüne aldığımızda öncelikli olarak, olay metoduna özel bilgilerin aktarılmasını sağlayacak şekilde bir tipin geliştirilmesi gerekmektedir. Projemize StokAzaldiEventArgs adında bir sınıf ekleyip aşağıdaki tasarımı gerçekleştiriniz. 25