Merhaba, C# Interface Kavramı ve Kullanımı yazım ile C# eğitim setime devam ediyorum. Bu dersimizde C# Interface Kavramı yani Arayüz kavramına bakacağız. C# Interface Kavramı Object Oriented Programming (OOP) (Nesne Yönelimli Programlama) konusunun 4 temel prensibinden birisidir. Interface ile sınıflara ait metotlar belirleyebiliyoruz.
OOP Nedir?
Object Oriented Programming (OOP), Nesne Yönelimli Programlama (NYP) nedir sorusunda ne kısa cevap, gerçek hayattaki her şeyin bilgisayar ortamında tanımlanması olarak cevap verebiliriz. Örneğin, Motorlu araçların ortak özelliklerini bir sınıfta tanımladık. Motorlu araçlar sınıfında, havada, denizde ve karada giden motorlu araçlar sınıflarını tanımladık. Karada giden araçlar sınıfında Otomobilleri tanımladık. Otomobiller sınıfında X bir markayı tanımladık. Her sınıf bir üst kategorisinin sınıfından miras alır. Böylece XX Markası dediğimizde o sınıfın, karada giden motorlu bir taşıt olduğunu biliriz. İşte tüm bu yapıya OOP Türkçe ifadesi ile NYP deriz.
Daha detaylı bilgi için bkz Wikipedia.
C# Interface Kavramı ve Kullanımı
Interface, OOP konusunda önemli bir yeri var demiştik. Bir sınıfa Interface ataması yaparak, o sınıfa özel metotlar üretip kullanabiliriz. Bir sınıfa birden fazla Interface (implement) uygulayabilir / giydirebiliriz. Interface içerisine metot tanımlaması yaparız ama işlemleri yazmayız. Yapılmasını istediğimiz işlemleri, Interface ‘i uyguladığımız sınıf içerisine yazarız.
Eğer bir sınıfa Interface uygulanmışsa yani implement edilmişse, o Interface içindeki metotlar mutlaka sınıfta da uygulanmalı yani implement edilmek zorundadır. Önceki derslerim olan C# Inheritance – C# Miras Kavramı ve C# Class Encapsulation derslerim için hazırladığım uygulama içerisinde Interface konusu da ekleyeceğim. En başta hepsini ayrı projeler olarak hazırlamayı düşünmüştüm ama bu konuların hepsi de OOP ile ilgili olduğundan hepsini tek proje içerisinde uygulayarak güzel bir kaynak oluşturabilirim diye düşündüm.
Bu dersin konusu olan C# Interface Kavramı konusunda yine aynı proje içerisinde kullanacağım.
Şimdi projeme bir klasör ekliyorum ve adına Interface yazıyorum. Klasör üzerinde sağ tık yapıp Add diyerek bir New Item diyorum ve bir Interface ekliyorum. Bu Interface’in adına da SQLWorks diyorum. Çünkü hali hazırda olan bir sınıfıma uygulayacağım ve bu Interface içine Save(), Update() ve Delete() metotlarını ekleyeceğim .
SQLWorks.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace C_sharp_Inheritance.Interface { interface SQLWorks { object Save(); object Update(int id); object Delete(int id); } }
Interface bu kadar. Burada açıklayacak bir şey yok. :)
Şimdi Student sınıfıma bu arayüzü uygulayacağım. Bu uygulamayı yaptıktan sonra sınıf içerisinde bir çok değişiklik yapmam gerekecek. Hep aynı proje üzerinden gittiğimden dolayı, Teacher sınıfına dokunmayacağım ki aradaki farkları görebilesiniz.
Önceki derslerden biliyorsunuz. Student sınıfı, Person sınıfından miras alıyordu. Şimdi ek olarak birde Interface uyguluyoruz. Uygulama şekli aşağıdaki gibidir.
public class Student : Person, Interface.SQLWorks
Person sınıfından sonra bir virgül atarak Interface’i ekliyoruz. Burada Inteface içerisine eklediğimiz metotları implement etmemiz gerekiyor aksi takdirde hata alırız.
Hatanın anlamı, “Student sınıfı, Interface üyesi olan SQLWorks.Save() metodunu içermiyor”.
Şimdi Interface metotlarımızı Student sınıfına ekleyelim.
İlk olarak, altı çizili olan kodun üzerine gelip, sarı renkle işaretlenmiş olan simgeye tıkladığımızda çıkan Implement Interface’e tıklarsak, Interface metotları otomatik olarak implement edilecektir.
Student sınıfında bir çok düzenleme yaptığımı söylemiştim. Şimdi biraz onlara bakalım. Student sınıfını olduğu gibi veriyorum.
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Windows.Forms; namespace C_sharp_Inheritance.Inheritance.Person { public class Student : Person, Interface.SQLWorks /* Student Class'a -- Interface.SQLWorks Interface(Arayüz) -- uyguluyoruz. * Class'ın en altında Interface'den gelen ve mecburi eklenmesi gereken metodlar var.*/ { public override void makeAction() { } public Student() { makeDataTable(); } private DataRow datarow; public static DataTable StudentDataTable = new DataTable(); // datatable static olmazsa class her çalıştırıldığında yeniden create edileceğinden datagridview'e sadece son eklenen satır gelir. // Static olunca formda class tanımlandığı için form açılmadan create edilir ve bir form tekrar açılana kadar tekrar create edilmez. private void makeDataTable() // datatable'a kolonları ekler. { StudentDataTable.Columns.Add("ID"); StudentDataTable.Columns.Add("Adı"); StudentDataTable.Columns.Add("Soyadı"); StudentDataTable.Columns.Add("DogumTarihi"); StudentDataTable.Columns.Add("Cinsiyeti"); StudentDataTable.Columns.Add("Okul"); } private int ID; // Stundent nesnesinde kullanacağımız bir değişken tanımlıyoruz. private string Okul; // Stundent nesnesinde kullanacağımız bir değişken tanımlıyoruz. public Student(string adi, string soyadi, DateTime dogum_tarih, string cinsiyet, string okul, int ID = 0) // varsyılan değerli parametre. Dışarıdan gönderilmesi zorunlu değildir. { this.Adı = adi; this.Soyadı = soyadi; this.DogumTarihi = dogum_tarih; this.Cinsiyeti = cinsiyet; this.Okul = okul; if (ID == 0) // ID 0 geliyorsa inserttir try { this.ID = Convert.ToInt32(StudentDataTable.Rows[StudentDataTable.Rows.Count - 1]["ID"]) + 1; // sıradaki ID'yi istedik. } catch (IndexOutOfRangeException) { this.ID = 1; // Eğer DataTable boş ise 1 verecek } else this.ID = ID; // Dışarıdan ID bilgisi gelmişse onu kullanacağız. datarow = CreateDrow(this); // gelen verilerden bir datarow ürettik StudentDataTable.Rows.Add(datarow); // datarow'u datatable'a ekledik. } private DataRow CreateDrow(Student item) // Datatable için bir datarow üretir. { DataRow userRow = StudentDataTable.NewRow(); userRow["ID"] = item.ID; userRow["Adı"] = item.Adı; userRow["Soyadı"] = item.Soyadı; userRow["DogumTarihi"] = item.DogumTarihi; userRow["Cinsiyeti"] = item.Cinsiyeti; userRow["Okul"] = item.Okul; return userRow; } // Miras Alınan Sınıftan gelen metodlar public override void Calis() { MessageBox.Show("Çalıştım"); } public override void SuIc() { MessageBox.Show("Su İçtim"); } public override void Uyu() { MessageBox.Show("Uyudum"); } public override void YemekYe() { MessageBox.Show("Yemek Yedim"); } // Miras Alınan Sınıftan gelen metodlar //SQLWorks Interface / Arayüzünden gelen metodlar.Eklenmesi zorunludur. public object Save() { return null; } public object Update(int id) { return null; } public object Delete(int id) { var query = StudentDataTable.AsEnumerable().Where(r => r.Field<string>("ID") == id.ToString()); foreach (var row in query.ToList()) row.Delete(); StudentDataTable.AcceptChanges(); return true; } // SQLWorks Interface / Arayüzünden gelen metodlar. Eklenmesi zorunludur. } }
Yapılan düzenlemeleri incleyelim;
- Delete işleminde kullanmak için ID değişkeni eklendi.
- Private bir DataRow ve Public Statik olarak bir DataTable eklendi. Statik olmasının sebebi yorum satırlarında yer alıyor.
- makeDataTable() metodunda sadece kullancağımız DataTable nesnesine kolonları ekleyecek şekilde düzenlendi.
- Constructor metoduna ID değişkenini ekledik ve kayıt ekleme işlemi için varsayılan olarak bir değer almasını istedik.
- Parametre alan Constructor metodunu kullanarak gönderdiğimiz verilerden bir DataRow üretip, DataTable’a yükledik.
- makeDataTable() metodunun içinde olan Row üretme ve doldurma kodlarını da ayrı bir metoda aldık.
- Interface ‘den gelen metotları implement ettik.
- Implement edilen Delete() metoduna işlemleri yazdık. Gelen ID bilgisine göre LINQ kullanarak DataTable’den ilgili satırı sildik.
Elbette tüm değişiklikle sınıflarda değil. Form1 içindeki Student ile ilgili işlemleri de değiştirdik.
Form1.cs
Sadece Student ile ilgili kodlar.
#region Inheritance Student Inheritance.Person.Student student = new Inheritance.Person.Student(); private void btn_studen_ekle_Click(object sender, EventArgs e) { student = new Inheritance.Person.Student(txt_Student_Ad.Text, txt_Student_soyAd.Text, dt_Student_dogum_Tar.Value, txt_StStudent_cinsiyet.Text, txt_Student_okul.Text); st_listele(); } private void btn_student_liste_Click(object sender, EventArgs e) { st_listele(); } void st_listele() { dataGridView1.DataSource = Inheritance.Person.Student.StudentDataTable; } #endregion // ....... private void btn_sil_Click(object sender, EventArgs e) { try { int ID = Convert.ToInt32(row.Cells["ID"].Value.ToString()); student.Delete(ID); // Bu delete işlemi SQLWorks Interface sayesinde oluyor. Sınıfa özel üretilmiş bir metod. } catch (ArgumentException) { MessageBox.Show("Bir satıra tıklamanız gerekiyor."); } dataGridView1.DataSource = Inheritance.Person.Student.StudentDataTable; } DataGridViewRow row; private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0) row = this.dataGridView1.Rows[e.RowIndex]; }
Bu kısımdaki değişiklikler;
- List<Student> kaldırıldı.
- List’e ekleme işlemi kaldırıldı
- Class seviyesinde tanımlanan Student nesnesi kullanılarak, yeni bir Student eklendi. Gerekli işlemler, Student sınıfında yapılıyor.
- Forma bir Sil Button ‘u eklendi.
- Kaydı silebilmek için DataGirdView nesnesinden tıklanılan satırın ID kolonundaki bilgiyi aldık.
- Alınan ID bilgisini Student.Delete() metoduna göndererek silme işlemini tamamladık.
Görselde gördüğünüz gibi, Inteface ile metotları implement ettiğimiz için, student. dediğimizde kullanılabilecek metotlar olarak listede görünüyor.
Interface kullanmanın en büyük faydası, benzer işlemler yapan sınıflara bir düzen getirmesidir diyebiliriz. Örneğin bu projede, Student, Teacher ve Worker sınıfları var. Bunları aslında bir database’e yazmak isteriz. Hazırladığımız SQLWorks Interface’ini tüm bu sınıflara uygulayarak, tüm sınıfların aynı metotlara sahip olmasını sağlıyoruz. Diğer bir deyişle sınflara kurallar getiriyoruz. Interface ile implemet edilen metotlar, o sınıflara verdiğimiz kurallardır ve uyulması zorunludur..
Interface’in en büyük özelliği, örneğini aldığımız yani ürettiğimiz nesnenin türüne bakmadan tek seferde işlem yapabiliriz. Aşağıdaki kodları incelerseniz daha net anlayacaksınız.
Interface.SQLWorks[] works = new Interface.SQLWorks[2]; student = new Inheritance.Person.Student(); works[0] = student; Inheritance.Person.Worker worker = new Inheritance.Person.Worker(); works[0] = worker; for (int i = 0; i < works.Length; i++) { works[i].Save(); }
Yukarıda gördüğünüz gibi SQLWorks Interface’inin uygulandığı tüm sınıflar için toplu olarak işlem yapabiliriz. Bir SQLWorks dizisi oluşturduk ve bu diziye hem Student hemde Worker örneklerini verdik. Bu sınıfların ikisi de, SQLWorks Interface üzerinden gelen Save() metotların sahip olduklarından toplu olarak işlem gerçekleştirebiliyoruz. Üstelik burada, örneğini aldığımız sınıfa ait Save() metodu çalışacak.
For döngüsünde sıra Student’e geldiğinde Student içindeki Save(), Worker’a geldiğinde Worker içindeki Save() metodu çalışacak.
Bir sonraki dersimiz Polymorphism olacak ve yine aynı proje içerisinde anlatılacak.
C# Interface Kavramı ve Kullanımı yazımda bu kadar arkadaşlar. Umarım C# Interface Kavramı ve Kullanımı kavramını güzelce açıklayabilmişimdir.
Bana destek olmak isterseniz, iletişim sayfamda verdiğim sosyal medya hesaplarımı takip edebilirsiniz.
C Sharp Eğitim Seti eğitimi sayfasına gitmek için tıklayınız. Derslerime özel olarak hazırladığım Github Projeme bu bağlantıdan ulaşabilirsiniz… Bu ders için hazırlanan projenin kodlarına buraya tıklayarak ulaşabilirsiniz.
Bu yazı, sitemdeki 430. yazıdır…
Sağlıcakla ve takipte kalın. ;)