Java - Soyut (Abstract) Sınıf ve Method Kullanımı

Java - Soyut (Abstract) Sınıf ve Method Kullanımı

Arkadaşlar merhaba,

Java dersleri serimize Java'da abstract sınıf ve methodların kullanımı ile devam ediyoruz.

Soyut Sınıflar (Abstract Class)

Soyutlama, yalnızca temel nitelikleri gösteren ve gereksiz bilgileri gizleyen nesne yönelimli programlama kavramıdır.Soyutlamanın temel amacı, gereksiz detayları kullanıcılardan gizlemektir.

Abstract class, ortak özellikleri olan nesneleri bir çatı altında toplamak için kullanılır.

Soyut Sınıf, OOP'lerde bir veya daha fazla soyut method bildiren bir sınıf türüdür. Bu sınıfların soyut metotları olabileceği gibi somut metotları da olabilir. Normal bir sınıf soyut methodlara sahip olamaz.

  • Soyut sınıflar final ve private olamazlar.

  • Bir soyut metot public yada protected olabilir.

  • Soyut sınıflar somutlaştırılamasa da, yine de alt sınıfları tarafından yapıcılar aracılığıyla başlatılırlar (initialized).

  • Genellikle Base Class tanımlamak için kullanılan ve soyutlama yeteneği kazandıran sınıflardır.

  • Abstract class, is-a ilişkilerinde kullanılır.

Aslında, bir soyut sınıf, variables, statik ve instance methods ve inner sınıflar dahil olmak üzere, soyut olmayan bir sınıfla aynı üyelerin tümünü içerebilir.

Soyut bir sınıf en çok, başka bir sınıfın belirli bir sınıfın özelliklerini miras almasını istediğinizde, ancak alt sınıfın bazı uygulama ayrıntılarını doldurmasını istediğinizde kullanılır.

abstract class Employee {

    abstract String getName();

    public void printName(){
        System.out.println(getName());
    }

    public void salary(){}

    // constructor

    public Employee() {
        System.out.println(getName());
    }
}

class TraineeEmployee extends Employee{
    String getName(){
        return  "Ahmet";
    }

    public static void main(String[] args) {
       new TraineeEmployee(); //Ahmet
    }

}

class Director extends Employee{

    @Override
    String getName() {
        return  "Umut";
    }

    public static void main(String[] args) {
            new Director().printName(); // Umut
    }
}

Soyut bir sınıfın herhangi bir soyut method bildirmesi gerekmese de, soyut bir method yalnızca soyut bir sınıfta veya interfacelerde tanımlanabilir.

Soyut bir sınıfın en önemli özelliklerinden biri, aslında herhangi bir soyut method içermesi gerekmemesidir. Örneğin, aşağıdaki kod, herhangi bir soyut method tanımlamasa da derlenir.

 public void salary(){}

final değiştirici gibi, abstract değiştirici, bu Tiger sınıfında gösterildiği bu Tiger sınıfında gösterildiği gibi, sınıf ve method bildirimlerinde erişim değiştiricisinden önce veya sonra yerleştirilebilir:

abstract public class Tiger {
        abstract public int claw();
}


// yanlış kullanımlar;

public class abstract Jackal { }// DOES NOT COMPILE
public int abstract howl(); // DOES NOT COMPILE

Bir gövdesi veya default implementation'ı olan soyut bir method tanımlamak mümkün değildir !

Yine de bir gövde ile bir method tanımlayabilirsiniz onu soyut olarak işaretlemeden tanımlayabilirsiniz. Method'u final olarak işaretlemediğiniz sürece, alt sınıfın devralınan bir methodu override etme seçeneği vardır.

Soyut sınıflar somutlaştırılamasa da, yine de alt sınıfları tarafından yapıcılar aracılığıyla başlatılırlar demiştik...

abstract class Employee {

    abstract String getName();

    public void printName(){
        System.out.println(getName());
    }

    public void salary(){}

    // constructor

}

class TraineeEmployee extends Employee{

    String getName(){
        return  "Ahmet";
    }

    public static void main(String[] args) {
       new TraineeEmployee();
    }

}

Derleyici, ilk olarak Employee sınıfında super() öğesini çağıran TraineeEmployee sınıfına default-constructor ekler.

Employee constructor sadece, bir alt sınıf aracılığı ile başlatıldığında çağırılır.

Soyut sınıftaki bir kurucu ile somut bir sınıf arasındaki temel fark, soyut sınıftaki bir kurucunun yalnızca somut bir alt sınıf tarafından başlatıldığında çağrılabilmesidir. Soyut sınıflar somutlaştırılamadığı için bu mantıklıdır.

public abstract final class Tortoise { // DOES NOT COMPILE

public abstract final void walk(); // DOES NOT COMPILE

Bir sınıfı veya methodu hem soyut hem de final olarak işaretlerseniz ne olur ?

Abstract bir şeyi işaretlerseniz, bir başkasının onu genişletmesini veya uygulamasını istiyorsunuz. Ancak, bir şeyi final olarak işaretlerseniz, herhangi birinin onu genişletmesini veya uygulamasını engellemiş olursunuz.

Bu uyumsuzluk nedeniyle Java, bir sınıfın veya methodun hem soyut hem de final olarak işaretlenmesine izin vermez.

abstract class Employee {

    private void salary(){}

}

class TraineeEmployee extends Employee{

    protected void salary(){}

}

Bu örnekte, Employee üst sınıfında tanımlanan soyut private method salary() , TraineeEmployee alt sınıfı tarafından görülmez.

TraineeEmployee bir implementation sağlasa da, soyut method inherit olmadığı için soyut methodun override edilmesi olarak kabul edilmez.

Derleyici bunu üst sınıfta tanır ve aynı methoda private ve abstract uygulandığı anda bir hata bildirir.

Bir methodu abstract ve private olarak bildirmek mümkün olmasa da, bir methodu final ve private olarak bildirmek (gereksiz de olsa) mümkündür.

abstract class Employee {

    abstract static void salary(); // does not compile
}

Statik bir method override edilemez. Sınıfın bir instance'sine değil, sınıfa ait olarak tanımlanır.

Statik bir method override edilemiyorsa hiçbir zaman implement edilemeyeceği için soyut olarak da işaretlenemez.

Soyut bir sınıfı genişleten ilk somut alt sınıf, devralınan tüm soyut methodları uygulaması zorunludur.

public class Manager extends Employee{

    @Override
    String getName() {
        return null;
    }
}

Manager ilk alt sınıf ise bu örnekte devraldığı tüm soyut metotları implement etmelidir.

Bu olmadığında derleyici bir hata bildirir.

Soyut bir sınıf , somut bir sınıfı genişletebilir ve bunun terside geçerlidir.

abstract class Employee {

    abstract String firstName();

    abstract String lastName();

}

abstract class Manager extends Employee{

    @Override
    String getName() {
        return null;
    }
}


class Director extends Employee{

    @Override
    String getName() {
        return  "Umut";
    }

 @Override
    void salary() {

  }

    public static void main(String[] args) {
            new Director().printName();
    }
}

Bu örnekte Director somut alt sınıf iken Manager ve Employee soyut sınıftır.

Director sınıf Employee sınıfını devraldığı için bu metotları devralması gerekir. Peki Director sınıf Manager sınıfı devralmış olsaydı ?

class Director extends Manager{

    @Override
    String getName() {
        return  "Umut";
    }

    @Override
    void salary() {}

}

abstract class Manager extends Employee{

    @Override
    void premiumPayment() {

    }
    @Override
    String getName() {
        return null;
    }
}

Üst sınıf Manager premiumPayment() methodunun bir implementationı'nı sağladığında method Director sınıfında soyut olmayan bir method olarak devralınır.

premiumPayment() methodunun override edilmesi de zorunlu değildir.

Aşağıdaki örnekte de görüldüğü gibi soyut bir sınıf somut sınıfı genişletebilir.

abstract class Manager extends Director {

    @Override
    void premiumPayment() {
    }

    @Override
    String getName() {
        return null;
    }
}

Soyut Sınıf ve Metot Tanımlama Kuralları

Kuralları genel olarak sıralayalım.

Soyut Sınıf Kuralları;

  • Soyut sınıflar somutlaştırılamaz.
  • Soyut sınıflar final olarak işaretlenemez.
  • Soyut sınıflar, sıfır veya daha fazla soyut ve soyut olmayan methodlar içerebilir.
  • Başka bir soyut sınıfı genişleten(extend eden) bir soyut sınıf, tüm soyut metotları devralır.
  • Soyut bir sınıfı genişleten ilk somut sınıf, devralınan tüm soyut method'lar için bir implementation sağlamalıdır.
  • Soyut sınıf constructors'ları, yalnızca bir alt sınıfın başlatılmasının bir parçası olarak çağrılabilmeleri dışında, normal kurucular olarak başlatma için aynı kuralları takip eder.
  • Soyut methodlar için bu kurallar, soyut methodun bir soyut sınıfta veya interface'de tanımlanıp tanımlanmadığına bakılmaksızın geçerlidir.

Soyut Method Kuralları;

  • Soyut methodlar, yalnızca soyut sınıflarda veya interface'lerde tanımlanabilir.

  • Soyut methodlar private veya final olarak tanımlanamaz.,

  • Soyut methodlar bildirildikleri soyut sınıfta metot gövdesi/implementation sağlamamalıdır.

  • Bir methodu override etmek için bir soyut method alt sınıfını uygulamak, kovaryant dönüş türleri, exception bildirimleri vb. dahil olmak üzere aynı kuralları takip eder.

Şimdilik yazımı burada sonlandırıyorum. Umarım faydalı olur.