Uzun bir aradan sonra tekrar merhaba.Bu yazımda Java da Inheritance,Polymorphism,Abstract ve SuperClass konularına değineceğim.

“Inheritance (kalıtım) ve polymorphism (çokbiçimlilik) OOP (Nesneye Yönelik Programlama)’de çoğunlukla bir arada kullanılan kardeş kavramlardır.”

Inheritance bir sınıfın sahip olduğu özelliklerin ve davranışların başka alt sınıflar tarafından kullanılabilmesine olanak sağlaması olarak açıklanabilir.

images

Şekilde Vehicle (araçlar) sınıfının altında bir adet Wheeled Vehicle (tekerlekli araçlar) sınıfı bulunmakta. Tekerlekli araçlar sınıfının altında ise bu araçlardan farklı kapı sayısına sahip olanların birbirlerinden ayrıldığını görebilirsiniz. Bu yapı bize kalıtımın pratikte nasıl uygulanabileceğini gösteriyor.

Bütün otomobiller ve bisikletler tekerlekli birer araçtır, o halde bunları “tekerlekli araçlar” sınıfı altında toplamamız mantıklı olur. Aynı zamanda yelkenliyle tekerlekli araçlarda de birer araçtır. O halde bunları da “araçlar” sınıfı altında birleştirmemiz mantıklı olur. Bu yapıya bir sandal ekleyecek olsak belki de yelkenli ile sandalı da “dümenli araçlar” sınıfı altına almak mantıklı olurdu.

Kalıtım kavramı en genel haliyle bu şekilde açıklanabilir, gelelim bir diğer kavrama.

2 kapılı ve 4 kapılı otomobillerin ortak özellilkeri;

  • Tekerlekleri vardır
  • Motorları vardır
  • İnsan taşırlar
  • Sürücüye ihtiyaç duyarlar
  • Yakıt tüketirler

Otomobil ile bisikletin ortak noktaları bulunmakta;

  • Tekerlekleri vardır
  • İnsan taşırlar
  • Sürücüye ihtiyaç duyarlar

Tekerlekli araçların yelkenliyle ortak noktaları vardır;

  • İnsan taşırlar
  • Sürücüye ihtiyaç duyarlar

Görüldüğü gibi aslında “İnsan taşıma” ve “sürücüye ihtiyaç duyma” gibi bilgileri çok kez tekrar etmiş olduk. Bu bilgilerin her birini ayrı ayrı bu sınıfların içinde tutmamıza gerek var mı? Madem inheritance bize “babadan oğula” geçiş sağlıyor. Ortak olan bu özellikleri “Vehicle” sınıfında tanımlayalım. Bütün sınıfın altındaki bütün araçlar o bilgileri tek bir yerden alsın. Böylece bir şeyi güncellememiz gerektiğinde (insanlar artık zombi olduğunda) sadece Vehicles sınıfında ilgili tanımı (insan taşırlar -> zombi taşırlar) değiştirmemiz yeterli olacaktır. İşte buna da polymorphism diyoruz.

Polymorphism bir nesnenin ilgili özelliklerinin kopyasını alıp kullanabilme, onları uygun şekilde değiştirebilme (override) özelliği sunan bir kavramdır. Yukarıdaki örnekte araçlar sınıfının tekerlek özelliğini aldık ve bunu istediğimiz araca uygun şekilde değiştirdik (bisiklet için 2 tekerlek/ince/çapı büyük, otomobil için 4 tekerlek/kalın/çapı küçük).
Inheritance ve polymorphism nesneye yönelik programlama mantığının temel taşlarını oluşturan kavramlardan ikisidir. Bu kavramlar ne kadar iyi hayata geçirilirse uygulamanın kaliteside o ölçüde artacaktır.
Tabi ki kaliteli bir uygulama da sadece bu iki kavramı dört dörtlük pratiğe dökmekle gerçeklenmez diyerek noktayı koyalım.
Gelelim şu abstract zımbırtısına..
Abstract sınıflar içerisinde normal yani içi dolu metodların,değişkenlerin ve interface’lerdeki gibi abstract (boş) metodların tanımlanabildiği yapılardır.Bu sınıflar new kelimesi ile oluşturulamazlar.Abstract sınıflar,genellikle ortak özellikleri olan nesneleri tek bir çatı altında toplamak için kullanılır.
  • Abstract sınıflarda içi boş yada dolu metodlar tanımlanır.
  • Abstract sınıflardan new kelimesi ile nesne oluşturulmaz.
  • En az 1 abstract metod varsa sınıf abstract olmalıdır.
  • Bir sınıfı abstract sınıf yapmak için abstract kelimesi kullanılır.

Superclass ı da anlatıp uzunca bir örnek yapacağız değerleri okuyucular 🙂

Bir alt-sınıf ne zaman üst-sınıfına erişmek isterse super anahtar sözcüğünü kullanabilir. super ‘in kullanımı iki türlü olur. Birincisi, üst-sınıfa ait nesne yaratmak içindir. İkincisi, üst-sınıfın öğelerine erişmek içindir. Bundan sonraki örneklerde, bu işlerin nasıl yapıldığını göreceğiz.Biz örnekte kalıtım aldığımız sınıftaki constructor ı işleme alınmadan yani geçerek yalnızca asıl sınıftaki constructorı çalıştırmak için kullanacağız biraz karışık gelmiş olabilir örneği dikkatli inceleyin.

 

Bu örnekte classlar arasındaki hiyerarşiyi,override işlemlerini,extends,super ve abstract işlemlerini öğreneceksiniz.


 

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public abstract class  Employee {
    private String firstname;
    private String lastname;
    private String socialSecurityNumber;

//3-parametreli constructor oluşturduk.
    public Employee(String first, String last, String ssn) {
        firstname = first;
        lastname = last;
        socialSecurityNumber = ssn;

    }

    //isim set edildi.
public void setFirstname(String first) {
        firstname = first;


    }
//ismi return ettik.
    public String getFirstname() {

        return firstname;
    }
    //soyisim set edildi.
    public void setLastname(String last) {
        lastname = last;

    }
//souisim geri döndürüldü.
    public String getLastname() {
        return lastname;

    }
//sosyal güvenlik numarası set edildi.
    public void setSocialSecurityNumber(String ssn) {
        socialSecurityNumber = ssn;

    }
//aynı şekilde return işlemi.
    public String getSocialSecurityNumber() {
        return socialSecurityNumber;
    }
//override yani fonksiyon ezme işlemini gerçekleştirelim.
    @Override
    public String toString() {
        return String.format("%s %s \n social security number is: %s", getFirstname(), getLastname(), getSocialSecurityNumber());
        //String format paramatresini dikkatli incelerseniz. %s olarak belirlenen yerlere string türündeki fonksiyonların geldiğini görecekseniz.
        //Bu şekilde tüm yazılarınızı formatlayabilirsiniz
    }
    //abstract metod aşapıdaki gibi yazılır.abdstract nedir ne işe yarar kod bloğunun üstündeki yazıda  mevcut.
public abstract double earnings();
}

Employee sınıfını tanımladık ve içini doldurduk.Abstract olarak tanımlanan sınıfın içinde birde abstract fonksiyon yazdık ama içi boş kalıtım alıp dolduracağız.

 

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public class SalariedEmployee extends Employee //Kalıtım alma işlemi yapıldı.SalariedEmployee sınıfı Employee sınıfının özelliklerini aldı.
{
    //Değişkenleri tanımladım.
    private  double weeklySalary;
    //4-parametreli constructor kullanımı.
    public SalariedEmployee(String first,String last,String ssn,double salary) {
        super(first,last,ssn);//Bu işlem Employee constructor ının çalıştırılmamasını yani geçilmesini sağlar.
        setWeeklySalary(salary);//Fonksiyona salary değeri gönderlip fonksiyon çağırıldı.
    }
    public void setWeeklySalary(double salary){//Fonksiyon tanımlama ve basit if else kullanım yapısınıda aşağıda görebilirsiniz.
        if(salary>=0.0)
        {
            weeklySalary=salary;

        }
        else
            throw new IllegalArgumentException("Weekly salary must be>=0.0");//Bir uyarı fırlattık ekrana

    }
    public double getWeeklySalary(){return weeklySalary;}
//Artık bunları yazmıyorum aynı işlemler return ve override işlemini biliyoruz artık.
    @Override
    public double earnings(){
        return getWeeklySalary();
    }
    @Override
    public  String toString(){
        return String.format("Salaried Employee: %s\n%s: $% .2f",super.toString(),"weekly salary",getWeeklySalary());//super metodun çağıtırılması ve
        // string formatlama işlemi
        // % .2 vilgülen sonra ekrana 2 basamak yazılacağını belirttik

    }

}

Uzun farkındayım ama daha çok var devam 🙂

 

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public class HourlyEmployee extends Employee {//kalıtım alma işlemi
    private double wage;
    private double hours;
//5-parametreli constructor
    public HourlyEmployee(String first, String last, String ssn, double hourlyWage, double hoursWorked) {
        super(first, last, ssn);
        setWage(hourlyWage);
        setHours(hoursWorked);
    }

    public void setWage(double hourlyWage) {
        if (hourlyWage >= 0.0)
            wage = hourlyWage;
        else
            throw new IllegalArgumentException("Hourly wage must be >=0.0");
    }

    public double getWage() {

        return wage;
    }

    public void setHours(double hoursWorked) {
        if ((hoursWorked >= 0.0) && (hoursWorked <= 168.0)) hours = hoursWorked; else throw new IllegalArgumentException("Hours worked must be>=0.0 and <=168.0");
    }

    public double getHours() {
        return hours;
    }

    @Override
    public double earnings() {
        if (getHours() <= 40)
            return getWage() * getHours();
        else
            return 40 * getWage() + (getHours() - 40) * getWage() * 1.5;
    }

    @Override
    public String toString() {
        return String.format("hourly employee:%s\n%s: $%,.2f; %s: %,.2f", super.toString(), "hourly wage", getWage(), "hours worked", getHours());
    }

}

Gördüğünüz gibi sürekli Employee sınıfından kalıtım alıyoruz.Extends anahtar kelimesi ile gerçekleşiyor bu işlem değiştirmek istediğimiz fonksiyonları override anahtar kelimesi ile ezip değiştiriyoruz.

 

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public class CommissionEmployee extends Employee {
    private double grossSales;
    private double commissionRate;

    public CommissionEmployee(String first, String last, String ssn, double sales, double rate) {
        super(first, last, ssn);//Employee constructor devre dışı bırakıldı
        setGrossSales(sales);//Fonksyion çağırma
        setCommissionRate(rate);//Fonksiyon çağırma

    }

    public void setCommissionRate(double rate) {
        if (rate > 0.0 && rate < 1.0) commissionRate = rate; else throw new IllegalArgumentException("Commission Rate must be >0.0 and <1.0"); } //set-get işlemleri yapılması aşağıdaki gibidir. public double getCommissionRate() { return commissionRate; } public void setGrossSales(double sales) { if (sales >= 0.0)
            grossSales = sales;
        else
            throw new IllegalArgumentException("Gross sales must be>=0.0");
    }

    public double getGrossSales() {
        return grossSales;
    }

    @Override
    public double earnings() {
        return getCommissionRate() * getGrossSales();
    }

    @Override
    public String toString() {
        //Uzunca bir string formatlama işlemi gerçekleştirdim.Dikkatli inceleyin arkadaşlar.
        return String.format("%s: %s\n%s: $%,.2f;%s: %.2f", "comission employee", super.toString(), "gross sales", getGrossSales(), "commission rate", getCommissionRate());


    }
}

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public class BasePlusCommissionEmployee extends CommissionEmployee {
    private double baseSalary;

    public BasePlusCommissionEmployee(String first, String last, String ssn, double sales, double rate, double salary) {
        super(first, last, ssn, sales, rate);
        setBaseSalary(salary);

    }

    public void setBaseSalary(double salary) {
        if (salary >= 0.0)
            baseSalary = salary;
        else
            throw new IllegalArgumentException("Base salary must be>=0.0");
    }

    public double getBaseSalary() {
        return baseSalary;
    }

    @Override
    public double earnings() {
        return getBaseSalary() + super.earnings();
    }

    @Override
    public String toString() {
        return String.format("%s %s; %s: $%,.2f", "base salaried", super.toString(), "base salary", getBaseSalary());
    }
}

      Geldik en tatlı yerine ana fonksiyonumuzu yazıp şu uzun şeyi bir test edelim.Bokta çıkabilir bilemiyosunki 🙂    

 

/**
 * Created by Kerem Sırma on 29.10.2015.
 */
public class PayrollSystemTest
{
    public static void main(String[] args)//Programı test etme aşamasına geldik.Ana fonksiyonumuzu yazalım.
    {
        SalariedEmployee salariedEmployee=new SalariedEmployee("Ayse","Fatma","111-11-1111",800.00);////Sınıflardan nesneler türetim değerler gönderelim.
        HourlyEmployee hourlyEmployee=new HourlyEmployee("Ali","Fuat","222-22-2222",16.75,40);//Tabii ilk constructor lar çalışacak.
        CommissionEmployee commissionEmployee=new CommissionEmployee("Nazım","Hikmet","333-33-3333",10000,.06);
        BasePlusCommissionEmployee basePlusCommissionEmployee=new BasePlusCommissionEmployee("Can","Yücel","444-44-4444",5000,.04,300);
        System.out.println("Employees processed individually: \n");
        System.out.printf("%s\n%s: $%,.2f\n\n",salariedEmployee,"earned",salariedEmployee.earnings());//abstract fonksiyonumuzu çağırdık.
        System.out.printf("%s\n%s: $%,.2f\n\n",commissionEmployee,"earned",hourlyEmployee.earnings());//aynı şekilde
        System.out.printf("%s\n%s: $%,.2f\n\n",basePlusCommissionEmployee,"earned",basePlusCommissionEmployee.earnings());//aynı şekilde
        Employee[] employees=new Employee[4];//Employee sınıfından 4 eleman içerebilecek bir dizi türettim.
        employees[0]=salariedEmployee;//Dizinin her bir boşluğuna değerleri fırlatalım.
        employees[1]=hourlyEmployee;
        employees[2]=commissionEmployee;
        employees[3]=basePlusCommissionEmployee;
        System.out.println("Employess processed polymorphically:\n");

        for(Employee currentEmployee:employees)//For döngüsüyle dizinin tüm elemanlarını geziyorum.
        {
            System.out.println(currentEmployee);//Elemanları yazdırıyorum.
            if(currentEmployee instanceof  BasePlusCommissionEmployee)
            {
                /*Java'da geçersiz tip dönüşümü bir çalışma hatasına neden olur.
                Geçersiz tip dönüşümlerinin çoğu çalışma zamanında yakalanabilir.
                    Ancak sınıf hiyerarşisindeki tip dönüşümleri ancak çalışma zamanında algılabilen geçersiz tip dönüşümleri üretebilirler.
                Bu bir çalışma zamanı hatası fırlatır.Java bu durumlara çözüm bulabilmek için instanceof adında bir çalışma zamanı operatoru tanımlar.*/
                BasePlusCommissionEmployee employee=(BasePlusCommissionEmployee)currentEmployee;//tür dönüşümü yapıp nesne türettik
                employee.setBaseSalary(1.10*employee.getBaseSalary());//set fonksiyonunu çağırarak değer gönderdim.
                System.out.printf("new base salary with 10%% increase is: $%,.2f\n",employee.getBaseSalary());//get methodu çağırıldı.
            }
            System.out.printf("earned $%,.2f\n\n",currentEmployee.earnings());

        }

        for(int j=0;j<employees.length;j++)//oluşturduğum dizinin boyutu kadar aşağıdaki fonksiyonları her bir eleman için ayrı ayrı ekrana yazdıralım.
            System.out.printf("Employee %d is a %s\n",j,employees[j].getClass().getName());

    }
}


   Programı run ettik ve sonuçlar aşağıda görüldüğü gibi oldu.  

payroll1 payroll2
    Haydi iyi çalışmalar :)

Facebook'dan yorumla