İçeriğe geç
Educora
Orta17 dk9 / 18

Soyut sınıflar ve arayüzler

Soyut sınıflar ve metotlar, arayüzler, implements, varsayılan metotlar ve Comparable arayüzüyle sıralama.

Kendini test et
Bu derste öğreneceklerin
  • abstract bir sınıf ve metot yazmak ve bunları alt sınıflarda gerçekleştirmek
  • Bir arayüz tanımlamak ve bir sınıfta birden fazla arayüzü gerçekleştirmek
  • Soyut sınıf ile arayüz arasında seçim yapmak

Önceki dersteki Shape sınıfına tekrar bakalım: area() metodu 0 döndürüyordu. Peki “sadece bir şekil” nedir ve alanı neden sıfır olsun? Aslında new Shape() oluşturmanın hiçbir anlamı yoktur; Shape yalnızca genel bir fikirdir. Java bu tür fikirleri ifade etmek için iki araç sunar: soyut sınıflar ve arayüzler.

Soyut sınıflar

abstract olarak tanımlanmış bir sınıftan nesne oluşturulamaz; o yalnızca alt sınıflar için bir temeldir. Soyut bir sınıfta soyut metotlar bulunabilir: bunların başlığı vardır ama gövdesi yoktur. Her alt sınıf bu metotları mutlaka gerçekleştirmelidir. Bununla birlikte soyut bir sınıfta sıradan alanlar, yapıcılar ve hazır metotlar da olabilir.

Java
public class Main {
    public static void main(String[] args) {
        Payment[] payments = { new CardPayment(50), new CashPayment(20) };
        for (Payment p : payments) {
            p.process();
        }
    }
}

abstract class Payment {
    protected double amount;

    Payment(double amount) { this.amount = amount; }

    abstract double fee();

    void process() {
        System.out.println(getClass().getSimpleName() + ": " + amount + " + fee " + fee() + " = " + (amount + fee()));
    }
}

class CardPayment extends Payment {
    CardPayment(double amount) { super(amount); }
    @Override double fee() { return amount * 0.02; }
}

class CashPayment extends Payment {
    CashPayment(double amount) { super(amount); }
    @Override double fee() { return 0; }
}
Beklenen çıktı
CardPayment: 50.0 + fee 1.0 = 51.0
CashPayment: 20.0 + fee 0.0 = 20.0

Payment sınıfı bir ödemenin nasıl işlendiğini bilir (process metodu), ama komisyonun ne kadar olduğunu bilmez; bunu her ödeme türü kendisi söyler. getClass().getSimpleName() nesnenin gerçek sınıfının adını döndürür. new Payment(10) yazarsan derleyici şu hatayı verir: Payment is abstract; cannot be instantiated.

Arayüzler

Tanım
Arayüz

Bir sınıfın neler yapabildiğini tanımlayan bir sözleşme: genellikle gövdesiz metotlardan oluşan bir liste. Sınıf, implements anahtar kelimesiyle arayüzü gerçekleştirir ve tüm soyut metotlarını yazmak zorundadır.

Bir sınıf yalnızca bir sınıftan türeyebilir, ama istediği kadar arayüzü gerçekleştirebilir. Ördek hem uçabilir hem yüzebilir, uçak ise yalnızca uçabilir; oysa ortak bir üst sınıfları yoktur. Java 8'den beri arayüzlere gövdesi olan varsayılan (default) metotlar da yazılabilir: sınıf bunları olduğu gibi kullanabilir ya da geçersiz kılabilir.

Java
public class Main {
    public static void main(String[] args) {
        Duck duck = new Duck();
        Plane plane = new Plane();
        Flyable[] flyers = { duck, plane };
        for (Flyable f : flyers) {
            f.fly();
            f.land();
        }
        duck.swim();
    }
}

interface Flyable {
    void fly();

    default void land() {
        System.out.println("  ...landing safely");
    }
}

interface Swimmable {
    void swim();
}

class Duck implements Flyable, Swimmable {
    public void fly() { System.out.println("Duck flaps its wings"); }
    public void swim() { System.out.println("Duck swims in the lake"); }
}

class Plane implements Flyable {
    public void fly() { System.out.println("Plane starts its engines"); }
    @Override
    public void land() { System.out.println("  ...landing at Heydar Aliyev Airport"); }
}
Beklenen çıktı
Duck flaps its wings
  ...landing safely
Plane starts its engines
  ...landing at Heydar Aliyev Airport
Duck swims in the lake

Comparable: standart kütüphaneden bir arayüz

Java'nın kendi kütüphanesi de arayüzler üzerine kuruludur. Arrays.sort() sayıları ve karakter dizilerini sıralamayı bilir; peki ya kendi nesnelerin? Bir sınıf Comparable<Product> arayüzünü gerçekleştirir ve compareTo metodunu yazarsa Arrays.sort() onu da sıralayabilir. compareTo negatif bir sayı döndürürse o anki nesne önce gelir, pozitif bir sayı döndürürse sonra gelir; 0 ise eşitlik demektir.

Java
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Product[] cart = {
            new Product("Laptop", 1500),
            new Product("Pen", 1.2),
            new Product("Backpack", 45)
        };
        Arrays.sort(cart);
        System.out.println(Arrays.toString(cart));
    }
}

class Product implements Comparable<Product> {
    private final String name;
    private final double price;

    Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public int compareTo(Product other) {
        return Double.compare(this.price, other.price);
    }

    @Override
    public String toString() { return name + " " + price; }
}
Beklenen çıktı
[Pen 1.2, Backpack 45.0, Laptop 1500.0]

Hangisini seçmeli?

ÖzellikSoyut sınıfArayüz
Anahtar kelimeextendsimplements
Kaç tane kullanılabilir?yalnızca biristenen sayıda
Alanlarher türlü alanyalnızca sabitler
Yapıcıolabilirolamaz
Anlamı“bir …dır” (kartla ödeme bir ödemedir)“…ebilir” (ördek uçabilir)

Önemli noktalar

  • abstract bir sınıftan nesne oluşturulamaz; soyut metotlarını alt sınıflar gerçekleştirir.
  • Arayüz, bir sınıfın neler yapabildiğini belirten bir sözleşmedir; sınıf onu implements ile gerçekleştirir.
  • Bir sınıf tek bir sınıftan türeyebilir ama birçok arayüzü gerçekleştirebilir.
  • default metotların arayüzün içinde hazır bir gövdesi vardır.
  • Comparable ve compareTo, kendi nesnelerini Arrays.sort() ile sıralamanı sağlar.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
abstract class Animal için hangi satır derlenmez?