Veysel Uğur KIZMAZ

Abstract Class Nedir? C# ve Java ile Abstract Class Kullanımı

20.07.2014Okunma Sayısı: 13532Kategori: Yazılım Mühendisliği

​Birçoğunuz projelerinizde class ve interface’leri kullanıyorsunuz. Hatta bazılarınız sınıflara interface tanımı bile yapmıyor olabilirsiniz. Bu durum ihtiyaca ve projenin büyüklüğüne göre değişkenlik göstermektedir. Ben de küçük projelerde interface tanımlarına ihtiyaç duymadım. Bu makalede sizlere Abstract sınıfları anlatacağım. Projelerde özellikle sizden sonra gelecek yazılım geliştiricilerin, oluşturduğunuz temel sınıflar üzerinde değişiklik yapmasını birnevi önleyebilecek ve altyapınızı daha sağlam yapmanızı sağlayabilecek bir yapıdan bahsedeceğim.

Şöyle bir örnek düşünün: Müşteri bizden online satış sitesi istedi. Online satış sitesi projeleri, müşterinin isteklerine göre tahmin edilemeyecek kadar büyüyebilir. Eğer projenin başında mimarinizi doğru kurmazsanız uzun vadede ciddi problemlerle karşılaşabilirsiniz. Online satış sitesinde 2 tür kullanıcı olduğunu düşünelim: Müşteri ve personel. Müşterilerin ve personellerin yapacağı işlemler ve ekranlar birbirinden farklı olacaktır.

Müşterinin yapacağı işlemler:

  1. Profil güncelleme
  2. Sepete ürün ekleme
  3. Sepetten ürün silme
  4. Sepeti onaylama
  5. Sepeti satın alma

Personelin yapacağı işlemler:

  1. Müşteri bilgilerini güncelleme
  2. Müşteri bilgilerini silme
  3. Ürün ekleme
  4. Ürün güncelleme
  5. Ürün silme
  6. Ürün kategorisi ekleme
  7. Ürün kategorisi güncelleme
  8. Ürün kategorisi silme

Gerçek bir projede elbette bu işlemlerin sayısı çok fazla olacaktır. Burada örnek olması açısından iki rolün kısıtlı sayıda ve birbirinden farklı olan yetkilerini tanımladık. Her iki kullanıcı da sisteme farklı sayfalar  (kullanıcı giriş sayfası) üzerinden giriş yapsınlar. Burada yapacağımız işlem sayfaları oluşturup yetkilerin nasıl verileceğini göstermek değil, müşteri ve personelin ortak noktalarını bir sınıf altında toplamak. Yani, müşteri ve personel birer insan (ya da kişi) olduğu için, öncelikle bu iki kişinin ortak bilgilerini, oluşturacağımız Kisi sınıfında toplayalım. Kisi sınıfında kişinin kimlik numarası, adı, soyadı, cinsiyeti bilgileri bulunsun. Bunun yanında tüm kişiler sisteme giriş yapacağı için giriş yapma metodu, giriş yaptıktan sonra kişinin yetkilerinin alınması gerektiği için kişinin yetkilerini veritabanından alma metodu bulunsun. Giriş yapma metodu her iki kullanıcı için de sabit olacaktır fakat yetkileri veritabanından alma metodu role göre değişecektir. Metodları buna uygun şekilde tanımlayalım. (Yetki sınıfının sadece Ad isminde bir değeri olacaktır)

Yetki Sınıfı C#

public class Yetki
{
    public string Ad { get; set; }
}

Yetki Sınıfı Java:

public class Yetki {
	public Yetki(String ad){
		setAd(ad);
	}
	public Yetki(){}
	
	private String ad;
	
	public String getAd(){
		return this.ad;
	}
	public void setAd(String ad){
		this.ad = ad;
	}
}

Cinsiyet Enum

public enum Cinsiyet
{
    Kadin, Erkek
}

Kişi sınıfı C#

public class Kisi
{
    public string KimlikNo { get; set; }
    public string Ad { get; set; }
    public string Soyad { get; set; }
    public Cinsiyet Cinsiyet { get; set; }
    public void GirisYap(string sifre)
    {
        //Giriş işlemini yap. Başarılıysa kullanıcının yetkisini getir.
        var yetkiler = YetkiGetir();
        for (int i = 0; i < yetkiler.Count; i++)
        {
            Console.WriteLine(yetkiler[i].Ad);
        }
    }
    public virtual List<Yetki> YetkiGetir() { return null; }
}

Kişi Sınıfı Java

import java.util.ArrayList;

public class Kisi {
	private String kimlikNo;
	private String ad;
	private String soyad;
	private Cinsiyet cinsiyet;
	
	public String getKimlikNo() {
		return kimlikNo;
	}
	public void setKimlikNo(String kimlikNo) {
		this.kimlikNo = kimlikNo;
	}
	public String getAd() {
		return ad;
	}
	public void setAd(String ad) {
		this.ad = ad;
	}
	public String getSoyad() {
		return soyad;
	}
	public void setSoyad(String soyad) {
		this.soyad = soyad;
	}
	public Cinsiyet getCinsiyet() {
		return cinsiyet;
	}
	public void setCinsiyet(Cinsiyet cinsiyet) {
		this.cinsiyet = cinsiyet;
	}
	
	public void girisYap(String sifre){
		ArrayList<Yetki> yetkiler = yetkiGetir();
		for(int i = 0; i < yetkiler.size(); i++){
			System.out.println(yetkiler.get(i).getAd());
		}
	}
	public ArrayList<Yetki> yetkiGetir(){
		throw new UnsupportedOperationException();
	}
}

Kisi sınıfını tanımladıktan sonra Personel ve Musteri sınıflarını tanımlayalım. Personelin kişiden farklı olarak sicil numarası ve işe giriş tarihi bilgileri bulunsun. Müşterinin ise müşteri numarası ve sisteme kayıt tarihi bulunsun.

Personel Sınıfı C#

class Personel : Kisi
{
    public int SicilNo { get; set; }
    public DateTime IseGirisTarih { get; set; }

    public override List<Yetki> YetkiGetir()
    {
        //Personelin yetkilerini getir
        return new List<Yetki>
        {
            new Yetki{ Ad = "MUSTERIGUNCELLE" },
            new Yetki{ Ad = "MUSTERISIL" },
            new Yetki{ Ad = "URUNEKLE" },
            new Yetki{ Ad = "URUNGUNCELLE" },
            new Yetki{ Ad = "URUNSIL" },
            new Yetki{ Ad = "URUNKATEGORIEKLE" },
            new Yetki{ Ad = "URUNKATEGORIGUNCELLE" },
            new Yetki{ Ad = "URUNKATEGORISIL" }
        };
    }
}

Personel Sınıfı Java

import java.sql.Date;
import java.util.ArrayList;


public class Personel extends Kisi {
	private int sicilNo;
	private Date iseGiristarih;
	
	public int getSicilNo() {
		return sicilNo;
	}
	public void setSicilNo(int sicilNo) {
		this.sicilNo = sicilNo;
	}
	public Date getIseGiristarih() {
		return iseGiristarih;
	}
	public void setIseGiristarih(Date iseGiristarih) {
		this.iseGiristarih = iseGiristarih;
	}
	
	public ArrayList<Yetki> yetkiGetir(){
		ArrayList<Yetki> yetkiler = new ArrayList<Yetki>();
		yetkiler.add(new Yetki("MUSTERIGUNCELLE"));
		yetkiler.add(new Yetki("MUSTERISIL"));
		yetkiler.add(new Yetki("URUNEKLE"));
		yetkiler.add(new Yetki("URUNGUNCELLE"));
		yetkiler.add(new Yetki("URUNSIL"));
		yetkiler.add(new Yetki("URUNKATEGORIEKLE"));
		yetkiler.add(new Yetki("URUNKATEGORIGUNCELLE"));
		yetkiler.add(new Yetki("URUNKATEGORISIL"));
		
		return yetkiler;
	} 
}

Musteri Sınıfı C#

class Musteri : Kisi
{
    public int MusteriNo { get; set; }
    public DateTime KayitTarih { get; set; }

    public override List<Yetki> YetkiGetir()
    {
        //Müşterinin yetkilerini getir
        return new List<Yetki>
        {
            new Yetki{ Ad = "PROFILGUNCELLE" },
            new Yetki{ Ad = "SEPETEURUNEKLE" },
            new Yetki{ Ad = "SEPETTENURUNSIL" },
            new Yetki{ Ad = "SEPETIONAYLA" },
            new Yetki{ Ad = "SEPETISATINAL" }
        };
    }
}

Musteri sınıfı Java

import java.sql.Date;
import java.util.ArrayList;

public class Musteri extends Kisi{
	private int musteriNo;
	private Date kayitTarih;
	
	public int getMusteriNo() {
		return musteriNo;
	}
	public void setMusteriNo(int sicilNo) {
		this.musteriNo = sicilNo;
	}
	public Date getKayitTarih() {
		return kayitTarih;
	}
	public void setKayitTarih(Date iseGiristarih) {
		this.kayitTarih = iseGiristarih;
	}
	
	public ArrayList<Yetki> yetkiGetir(){
		ArrayList<Yetki> yetkiler = new ArrayList<Yetki>();
		yetkiler.add(new Yetki("PROFILGUNCELLE"));
		yetkiler.add(new Yetki("SEPETEURUNEKLE"));
		yetkiler.add(new Yetki("SEPETTENURUNSIL"));
		yetkiler.add(new Yetki("SEPETIONAYLA"));
		yetkiler.add(new Yetki("SEPETISATINAL"));
		
		return yetkiler;
	} 
}

Yeni bir müşteri oluşturmak için Musteri türünden bir nesne tanımlayıp bu nesnedeki bilgileri veritabanında MUSTERI ve KISI tablolarına ekleyebiliriz. Benzer şekilde yeni bir personel oluşturmak için Personel türünden bir nesne tanımlayıp bu nesnedeki bilgileri veritabanında PERSONEL ve KISI tablolarına ekleyebiliriz. Böylelikle KISI tablosundaki bir kaydın eğer personel ise PERSONEL tablosunda, müşteri ise MUSTERI tablosunda da bir kaydı bulunacaktır. Fakat şu anki yapıda yazılımcı tarafından Kisi sınıfı türünden bir nesne oluşturup veritabanındaki KISI sınıfına doğrudan kaydedilebilir. Eğer bu işlem yapılırsa, kişinin müşteri mi personel mi olduğu, müşteriyse müşteri bilgileri, personelse personel bilgileri veritabanında bulunmayacaktır. Kişinin doğrudan (new anahtar kelimesi ile) oluşturulmasını engellemek için Kisi sınıfını abstract olarak tanımlayabilirsiniz.

"Abstract sınıflar türünden (new anahtar kelimesi ile) bir nesne oluşturulamaz!"

Kisi sınıfını abstract yaptıktan sonra YetkiGetir metodunun, bu sınıfın kalıtımını alan diğer sınıflarda farklı kullanılabilmesi için bu metodu da abstract olarak tanımlamanız gerekmektedir. Böylelikle hem sınıf türünden nesne oluşturmanın önüne geçmiş oldunuz hem de Kisi sınıfının kalıtımını alan sınıflarda aynı isimde ama farklı içeriklerde metodlar oluşturabildiniz. Şimdi Kisi sınfını belirttiğimiz şekilde güncelleyelim.

Abstract Kisi sınıfı C#

abstract class Kisi
{
    public string KimlikNo { get; set; }
    public string Ad { get; set; }
    public string Soyad { get; set; }
    public Cinsiyet Cinsiyet { get; set; }
    public void GirisYap(string sifre)
    {
        //Giriş işlemini yap. Başarılıysa kullanıcının yetkisini getir.
        var yetkiler = YetkiGetir();
        for (int i = 0; i < yetkiler.Count; i++)
        {
            Console.WriteLine(yetkiler[i].Ad);
        }
    }
    public abstract List<Yetki> YetkiGetir();
}

Abstract Kisi sınıfı Java

import java.util.ArrayList;

public abstract class Kisi {
	private String kimlikNo;
	private String ad;
	private String soyad;
	private Cinsiyet cinsiyet;
	
	public String getKimlikNo() {
		return kimlikNo;
	}
	public void setKimlikNo(String kimlikNo) {
		this.kimlikNo = kimlikNo;
	}
	public String getAd() {
		return ad;
	}
	public void setAd(String ad) {
		this.ad = ad;
	}
	public String getSoyad() {
		return soyad;
	}
	public void setSoyad(String soyad) {
		this.soyad = soyad;
	}
	public Cinsiyet getCinsiyet() {
		return cinsiyet;
	}
	public void setCinsiyet(Cinsiyet cinsiyet) {
		this.cinsiyet = cinsiyet;
	}
	
	public void girisYap(String sifre){
		ArrayList<Yetki> yetkiler = yetkiGetir();
		for(int i = 0; i < yetkiler.size(); i++){
			System.out.println(yetkiler.get(i).getAd());
		}
	}
	public abstract ArrayList<Yetki> yetkiGetir();
}

YetkiGetir metodu, Kisi sınıfının kalıtımını alan Personel ve Musteri sınıflarında yine override anahtar kelimesi ile tanımlanacaktır.

Bu noktaya kadar kodlamanızı tamamladıktan sonra Kisi sınıfı türünden bir nesne oluşturmaya çalışın ve derleyicinin verdiği uyarı mesajını inceleyiniz.

Kisi Sınıfı Tanımlayamama C#

Kisi Sınıfı Tanımlayamama Java

Şimdi Personel ve Musteri türünden birer nesne (kullanıcı) oluşturun ve sırayla bu kullanıcıların sisteme girilerini yapınız.

Main Metodu C#

Personel veysel = new Personel();
Console.WriteLine("Personel Yetkileri:");
veysel.GirisYap("123");

Console.WriteLine("\n");

Musteri ugur = new Musteri();
Console.WriteLine("Müşteri Yetkileri:");
ugur.GirisYap("123");

Main Metodu Java

Personel veysel = new Personel();
System.out.println("Personel Yetkileri:");
veysel.girisYap("123");

System.out.println("\n");

Musteri ugur = new Musteri();
System.out.println("Müşteri Yetkileri:");
ugur.girisYap("123");

Kodlamayı tamamladıktan sonra programı çalıştırdığınızda, ekranda önce personel (veysel değişkeninin) yetkilerinin Personel sınıfının YetkiGetir metodundan alındığını,  sonra müşteri (ugur değişkeninin) yetkilerinin Musteri sınıfının YetkiGetir metodundan alındığını göreceksiniz.

İşlem Sonucu C#

İşlem Sonucu Java