• Anasayfa
  • Eğitimler
    • JavaScript Eğitimi
    • Angular 2 Eğitimi
    • React.js Eğitimi
    • Java 8 Eğitimi
    • Java EE 7 Eğitimi
    • Spring Framework Eğitimi
    • Git Eğitimi
  • Online Eğitimler
    • Online React.js Eğitimi
    • Online Angular 2 Eğitimi
    • Online Spring Boot Eğitimi
  • Referanslar
  • Hakkında
  • İletişim
KodEdu
  • Anasayfa
  • Eğitimler
    • JavaScript Eğitimi
    • Angular 2 Eğitimi
    • React.js Eğitimi
    • Java 8 Eğitimi
    • Java EE 7 Eğitimi
    • Spring Framework Eğitimi
    • Git Eğitimi
  • Online Eğitimler
    • Online React.js Eğitimi
    • Online Angular 2 Eğitimi
    • Online Spring Boot Eğitimi
  • Referanslar
  • Hakkında
  • İletişim

Java 8 – Default Methods

  • Posted by Kodedu
  • Categories backend, Genel, Uncategorized, Yazılar
  • Date 6 Ekim 2014

Java 8 ile beraber varsayılan metod özelliği bir dil özelliği olarak Java’ya katıldı. Varsayılan metodların literatürde birçok farklı isim ile anılmaktadır. Bunlar;

  • Default method
  • Defender method
  • Virtual extension method

Java 8 evvelinde arayüz bileşenlerinde dilin tasarımı açısından sadece soyut metodlar bulunabilmekteydi. Somut yani gövdeli metodlar bulunamamaktaydı. Aşağıda doğru ve yanlış kullanımlara birer örnek görmekteyiz.

Doğru bir kullanım örneği
public interface Arac {
    void gazla(); (1)
}
  1. Soyut, gövdesiz metod, doğru kullanım.
Yanlış bir kullanım örneği
public interface Arac {
    void gazla() {
     // bla bla bla
    }; (1)
}
  1. Somut, gövdeli metod, yanlış kullanım.

Varsayılan Metoda Giriş

Java 8 ile birlikte bir arayüz bileşeninde bir yada daha fazla sayıda defender method tanımlanabilmektedir. Varsayılan metodlar default anahtar kelimesiyle tanımlanmaktadır. Örneğin;

public interface Arac {

    default void gazla(){ // Defender method

        System.out.println("Araç:  çalışıyor..");

    }

    void dur(); // Soyut metod
}
  1. numaralı kısımdaki gazla() metodu default anahtar ifadesi aracılığıyla bir varsayılan metoda dönüştürülmüştür. Varsayılan metodlar arayüzlere iş mantığı yerleştirmeye müsade eden özel metodlardır.
  2. numaralı kısımda ise olağan biçimde gövdesiz bir metod bulunmaktadır.

Varsayılan metoda sahip bir arayüzden türeyen alt sınıflar, arayüzün sahip olduğu tüm defender metodları tüketebilmektedir.

Arac türünden Minibus sınıfı
public class Minibus implements Arac {

    @Override
    public void dur() {
        System.out.println("Minibüs duruyor..");
    }


}

Örneğin yukarıda yer alan Minibus sınıfı Arac`arayüzü türünden bir sınıftır. Bu sebeple, Minibus sınıfı türünden nesneler `Arac arayüzü içerisindeki gazla() metodunu koşturabilecektir.

Minibus minibus=new Minibus();
minibus.gazla(); (1)
minibus.dur(); (2)
  1. Arac içindeki gazla() varsayılan metodu koşturuluyor.
  2. Minibus içindeki dur() metodu koşturuluyor.
Araç:  çalışıyor..
Minibüs duruyor..

Yukarıda görüldüğü üzere, normalde Minibus sınıfı içerisinde gazla() metodu bulunmamasına rağmen, Arac arayüzü içindeki defender metodu koşturabildi.

Varsayılan metodlarda çakışma

Eğer bir Java sınıfı, aynı isimde varsayılan metoda sahip birden fazla arayüzü uygularsa, derleme zamanında hata ile karşılaşılır.

Aynı isimde varsayılan metodlara sahip iki arayüz
public interface Arac { (1)

    default void gazla(){
        System.out.println("Araç:  çalışıyor..");
    }

    void dur();
}

public interface Tasit { (2)

    default void gazla(){
        System.out.println("Taşıt: çalışıyor..");
    }
}

Örneğin (1) numarada Arac, (2) numarada da Tasit arayüzleri gazla() adında varsayılan metodlara sahiptir.

Şimdi bu iki türü birden uygulayan bir Otobus sınıfı yazalım.

Çakışma durumu örneği
public class Otobus implements Arac, Tasit {

    @Override
    public void dur() {
        System.out.println("Araç duruyor..");
    }
}

Otobus sınıfı bu haliyle derlendiğinde aşağıdaki derleme hatası alınacaktır.

Çakışma durumu hata mesajı
Error:(6, 8) java: class com.kodcu.def.Otobus inherits unrelated defaults for gazla() from types com.kodcu.def.Arac and com.kodcu.def.Tasit

Çünkü ortada  Otobus sınıfının hangi gazla() metodunu koşturacağına dair bir ikilem vardır. JVM ikilem durumlarını hiç sevmez, ona bir seçim şansız sunmalıyız.  Bu çakışma durumu, varsayılan metodu Otobus sınıfı içinde yeniden düzenlenerek (@Override ederek) giderilebilmektedir.

Çakışma durumunun giderilmesi – 1
public class Otobus implements Arac, Tasit {

    @Override
    public void dur() {
        System.out.println("Araç duruyor..");
    }

    @Override
    public void gazla() {
        System.out.println("Otobüs çalışıyor..");
    }
}

Otobus sınıfına gazla() metodu ekleyerek yeniden düzenlendiğinde artık çakışma durumu giderilmiş durumdadır. Sınıf bu haliyle Otobüs çalışıyor.. mesajını çıktılayacaktır.

Fakat burada farklı bir ihtiyaç daha göze batmaktadır. Bu durumda Arac veya Tasit arayüzleri içindeki çakışan gazla() metodları nasıl alt sınıflarda kullanılabilir?

İşte bu noktada <arayüz-adı>.super.<metod-adı>() biçimi ile arayüzlerdeki varsayılan metodlar çakışma olmadan koşturulabilmektedir.

Çakışma durumunun giderilmesi – 2
public class Otobus implements Arac, Tasit {

    @Override
    public void dur() {
        System.out.println("Araç duruyor..");
    }

    @Override
    public void gazla() {

        Arac.super.gazla(); (1)
            /* veya */
        Tasit.super.gazla(); (2)
    }
}
  1. Arac arayüzünün gazla() metodunu koşturur
  2. Tasit arayüzünün gazla() metodunu koşturur

Varsayılan metodlar ve Fonksiyonel arayüzler

Fonksiyonel arayüzler, tek bir gövdesiz metoda sahip özel arayüzlerdir. Eğer bir Java arayüzünün içinde birden fazla sayıda soyut metod varsa, bu arayüzler fonksiyonel arayüz olamamaktadır. Fonksiyonel arayüzlerin en önemli özelliği, Lambda ifadesi olarak temsil edilebilmesidir.

Arayüzler içinde tanımlanan varsayılan metodlar ise, bir arayüzün fonksiyonel olabilmesini etkilememektedir. Çünkü yazılan Lambda deyimleri, arayüz içindeki tek bir soyut metoda odaklı olarak dönüştürülmektedir.

public interface Arac {

    default void gazla(){
        System.out.println("Araç:  çalışıyor..");
    }

    void dur();
}

Örneğin yukarıdaki Arac arayüzünü fonksiyonel arayüz olabilirliği açısından değerlendirelim. Arac sınıfının fonksiyonel arayüz olabilmesi için tek bir soyut metoda sahip olması gerekmektedir. Arac arayüzü içindeki dur() metodu soyuti gövdesiz bir metod olduğu için bir fonksiyonel arayüzdür. gazla() metodu ise bir varsayılan metod olduğundan fonksiyonel olabilirliğe bir etkisi yoktur. Bu noktada, Arac arayüzü bir fonksiyonel arayüz olduğundan Lambda deyimi olarak yazılabilecektir. Tabi ki Lambda deyimi, dur() isimli soyut metod dikkate alınarak yazılmalıdır.

Arac otobus = ()-> System.out.println("Otobüs duruyor.."); (1)
otobus.gazla();
otobus.dur();
Araç:  çalışıyor..
Otobüs duruyor..

Yukarıda (1) numarada yazılı Lambda deyimi, dur() metoduna karşılık olarak tanımlanmıştır. Bu sebeple Arac arayüzü türünden bir nesne oluşturmaktadır.

Varsayılan metodlar ve JDK

JDK 1.8 içerisinde bazı noktalarda varsayılan metodlar kullanılmaktadır. java.util.Collection arayüzünde bunu fazlaca görmekteyiz.

public interface Collection<E> extends Iterable<E> {

    ...

    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    ...

    @Override
    default Spliterator spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    default Stream parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

Collection sınıfı içindeki removeIf, stream, parallelStream ve spliterator metodları varsayılan metodlardır. Bu sebeple Collection türünden tüm nesneler bu varsayılan metodları miras alarak tüketebilmektedir.

Collection arayüzünde olduğu gibi Iterable arayüzünde de varsayılan metod bulunduğunu görebiliyoruz.

@FunctionalInterface
public interface Iterable<T> {

    Iterator iterator();

    default void forEach(Consumer<? super T> action) {
    	Objects.requireNonNull(action);
    	for (T t : this) {
        	action.accept(t);
    	}
    }
}

Iterable#forEach varsayılan metodu sayesinde Iterable türünden tüm veri tipleri, bu metodu ortak olarak tüketebiliyor.

Tekrar görüşmek dileğiyle..

Tag:backend

  • Share:
author avatar
Kodedu

Previous post

Java 8 - Method Reference
6 Ekim 2014

Next post

Writing Books with Asciidoc FX
8 Ekim 2014

You may also like

api-logo
Swagger Nedir? Neden kullanılır?
10 Ekim, 2018
spring-cli-logo
Spring CLI ile Spring Boot Projeleri Hazırlamak
21 Ağustos, 2017
eureka_architecture
Spring Cloud Netflix ve Eureka Service Discovery
3 Temmuz, 2017

Leave A Reply Cevabı iptal et

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta listesine kayıt olun!






Gözde yazılar

Netmera ile Röportaj
18Haz2012
Spring CLI ile Spring Boot Projeleri Hazırlamak
21Ağu2017
Performans, Yük ve Stres Testleri
26Ağu2012
CDI – @Produces, @New ve @PostConstruct Notasyonları
22Tem2013

Son Yazılar

  • Java’da Record’lar 27 Ocak 2020
  • Swagger Nedir? Neden kullanılır? 10 Ekim 2018
  • Spring CLI ile Spring Boot Projeleri Hazırlamak 21 Ağustos 2017
  • Spring Cloud Netflix ve Eureka Service Discovery 3 Temmuz 2017
  • Online React.js Eğitimi ardından (15-25 Mayıs 2017) 31 Mayıs 2017

Son Yorumlar

  • Coupling ve Cohesion Kavramları Nedir? için Hilal
  • Naïve Bayes Sınıflandırma Algoritması için Rahman Usta
  • Naïve Bayes Sınıflandırma Algoritması için Mete
  • YAML Nedir? Neden YAML Kullanmalıyız? için kara
  • JWT (JSON Web Tokens) Nedir? Ne işe yarar? için Furkan

Get Java Software

Arşivler

Bizi takip edin

React.js Eğitimi Başlıyor
11-22 Eylül, 2017
Eğitmen
Rahman Usta
İletişim

merhaba@kodedu.com

  • Hakkında
  • Gizlilik Politikası
  • İletişim
  • Referanslar
Kodedu Bilişim Danışmanlık
Cemil Meriç mah. Çelebi sok.
No:16/3 Ümraniye/İSTANBUL
Tel: 0850 885 38 65
Alemdağ V.D.: 8960484815

KODEDU © Tüm hakları saklıdır.