Apa implementasi "default" dari metode yang ditentukan dalam Antarmuka?


91

Di Antarmuka Koleksi saya menemukan metode bernama removeIf() yang berisi implementasinya.

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

Saya ingin tahu apakah ada cara untuk mendefinisikan tubuh metode dalam sebuah antarmuka?
Apa defaultkata kuncinya dan bagaimana cara kerjanya?



Jawaban:


162

Dari https://dzone.com/articles/interface-default-methods-java

Java 8 memperkenalkan fitur baru “Metode Default” atau (Metode Pembela), yang memungkinkan pengembang untuk menambahkan metode baru ke antarmuka tanpa merusak implementasi yang ada dari antarmuka ini. Ini memberikan fleksibilitas untuk memungkinkan implementasi definisi antarmuka yang akan digunakan sebagai default dalam situasi di mana kelas konkret gagal menyediakan implementasi untuk metode itu.

public interface A {
    default void foo(){
       System.out.println("Calling A.foo()");
    }
}

public class ClassAB implements A {
}

Ada satu pertanyaan umum yang orang tanyakan tentang metode default ketika mereka mendengar tentang fitur baru untuk pertama kalinya:

Bagaimana jika kelas mengimplementasikan dua antarmuka dan kedua antarmuka tersebut mendefinisikan metode default dengan tanda tangan yang sama?

Contoh untuk menggambarkan situasi ini:

public interface A {  
    default void foo(){  
        System.out.println("Calling A.foo()");  
    }  
}

public interface B {
    default void foo(){
        System.out.println("Calling B.foo()");
    }
}


public class ClassAB implements A, B {

}  

Kode ini gagal untuk dikompilasi dengan hasil berikut:

java: class Clazz inherits unrelated defaults for foo() from types A and B

Untuk memperbaikinya, di Clazz, kita harus menyelesaikannya secara manual dengan mengganti metode yang bertentangan:

public class Clazz implements A, B {
    public void foo(){}
}

Tetapi bagaimana jika kita ingin memanggil implementasi default metode foo () dari antarmuka A daripada mengimplementasikannya sendiri.

Dimungkinkan untuk merujuk ke A # foo () sebagai berikut:

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}

19
Terima kasih, eksposisi yang sangat bagus. Anda menjawab semua pertanyaan saya sebelum saya sempat bertanya kepada mereka.
Jeff Hutchins

mengapa tidak menggunakan abstrak saja?
Astolfo Hoscher

1
@AstolfoHoscher Anda hanya dapat memperluas satu kelas, tetapi Anda dapat mengimplementasikan beberapa antarmuka.
Charles Wood

49

Metode tersebut disebut metode default. Metode default atau metode Defender adalah salah satu fitur yang baru ditambahkan di Java 8.

Mereka akan digunakan untuk memungkinkan metode antarmuka menyediakan implementasi yang digunakan sebagai default jika kelas konkret tidak menyediakan implementasi untuk metode itu.

Jadi, jika Anda memiliki antarmuka, dengan metode default:

public interface Hello {
    default void sayHello() {
        System.out.println("Hello");
    }
}

Kelas berikut sangat valid:

public class HelloImpl implements Hello {

}

Jika Anda membuat instance dari HelloImpl:

Hello hello = new HelloImpl();
hello.sayHello();  // This will invoke the default method in interface

Tautan Berguna:


Jadi tidak masalah jika kelas mengimplementasikan antarmuka dan tidak mengimplementasikan metodenya? Sejauh menyangkut Java7 yang saya gunakan, ini tidak diizinkan.
Aniket Thakur

2
@Aniketur. Ini tidak diperbolehkan sebelum Java 8. Fitur ini hanya ditambahkan di Java 8. Anda dapat menghindari penerapan metode default di kelas implementasi Anda.
Rohit Jain

1
@Tokopedia Lihat komentar saya sebelumnya. Tidak, Anda tidak perlu menyediakan implementasi metode antarmuka default dalam mengimplementasikan kelas.
Rohit Jain

1
@PawanMishra, Anda dapat menggantinya. Tidak ada batasan seperti Anda hanya perlu menggunakan implementasi default.
Aniket Thakur

4
Sebuah langkah maju yang pada akhirnya akan menghindari kebingungan oleh banyak warisan!
Xtreme Biker

17

Saya melakukan sedikit riset dan saya menemukan yang berikut ini. Semoga ini membantu.

Masalah yang ada

Metode antarmuka normal dideklarasikan sebagai abstrak dan harus didefinisikan di kelas yang mengimplementasikan antarmuka. Ini 'membebani' pelaksana kelas dengan tanggung jawab untuk mengimplementasikan setiap metode yang dideklarasikan. Lebih penting lagi, ini juga berarti bahwa memperluas antarmuka tidak mungkin dilakukan setelah 'publikasi'. Jika tidak, semua pelaksana harus menyesuaikan implementasinya, memutus sumber mundur dan kompatibilitas biner.

Solusi diadopsi di Java 8

Untuk mengatasi masalah ini, salah satu fitur baru JDK 8 adalah kemungkinan untuk memperluas antarmuka yang ada dengan metode default. Metode default tidak hanya dideklarasikan, tetapi juga ditentukan di antarmuka.

Poin penting untuk diperhatikan

  1. Pelaksana dapat memilih untuk tidak mengimplementasikan metode default dalam mengimplementasikan kelas.
  2. Pelaksana masih dapat mengganti metode default, seperti metode kelas non-final biasa dapat diganti dalam subkelas.
  3. Kelas abstrak bahkan dapat (kembali) mendeklarasikan metode default sebagai abstrak, memaksa subkelas untuk mengimplementasikan kembali metode tersebut (terkadang disebut 'abstraksi ulang').
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.