Secara eksplisit memanggil metode default di Jawa

247

Java 8 memperkenalkan metode standar untuk menyediakan kemampuan untuk memperluas antarmuka tanpa perlu memodifikasi implementasi yang ada.

Saya bertanya-tanya apakah mungkin untuk secara eksplisit memanggil implementasi default dari suatu metode ketika metode itu telah ditimpa atau tidak tersedia karena implementasi standar yang bertentangan di antarmuka yang berbeda.

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

class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }
    public void afoo() {
        // how to invoke A.foo() here?
    }
}

Mempertimbangkan kode di atas, bagaimana Anda akan memanggil A.foo()dari metode kelas B?

GOTO 0
sumber
Bisakah Anda memberi tahu saya mengapa Anda menerapkan metode foo () di dalam antarmuka Anda A ??.
Maciej Cygan
20
@MaciejCygan Diijinkan di Jawa 8
Rohit Jain

Jawaban:

330

Sesuai artikel ini Anda mengakses metode default di antarmuka Amenggunakan

A.super.foo();

Ini dapat digunakan sebagai berikut (dengan asumsi antarmuka Adan Ckeduanya memiliki metode default foo())

public class ChildClass implements A, C {
    @Override    
    public void foo() {
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    }
    public void bah() {
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    }
}

Adan Ckeduanya dapat memiliki .foo()metode dan implementasi standar spesifik dapat dipilih atau Anda dapat menggunakan satu (atau keduanya) sebagai bagian dari yang barufoo() metode . Anda juga dapat menggunakan sintaks yang sama untuk mengakses versi default dalam metode lain di kelas implementasi Anda.

Deskripsi formal sintaksis metode pemanggilan dapat ditemukan di bab 15 JLS .

Richard Tingle
sumber
14
Perhatikan juga bahwa jika A extends SomeOtherInterface, dan SomeOtherInterfacesudah default Type method(), maka Anda tidak bisa menelepon SomeOtherInterface.super.method()dari ChildClass saja. Anda hanya dapat memanggil metode default antarmuka yang disebutkan dalam ChildClass's implementsklausa, bukan orang tua mereka interface' metode.
gvlasov
1
@Suseika poin bagus, sama seperti tidak ada super.super.someMethod();(karena itu akan mengerikan)
Richard Tingle
@ titik bagus gvlasov, tetapi bagaimana mengakses metode default antarmuka orangtua dari antarmuka anak, apakah mungkin ?? Perbarui .......... Ya Kemungkinan, penjelasan yang lebih konkret di sini stackoverflow.com/a/24280376/3791156
Raaghu
@RichardTingle jawaban sempurna!
gaurav
17

Kode di bawah ini akan berfungsi.

public class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    void aFoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
        B b = new B();
        b.foo();
        b.aFoo();
    }
}

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

Keluaran:

B.foo
A.foo
Abhijith Nagarajan
sumber
Saya pikir ini adalah contoh terbaik yang menggambarkan pertanyaan di atas. Terima kasih
Hemanth Peela
8

Jawaban ini ditulis terutama untuk pengguna yang berasal dari pertanyaan 45047550 yang ditutup.

Antarmuka Java 8 memperkenalkan beberapa aspek pewarisan berganda. Metode default memiliki badan fungsi yang diimplementasikan. Untuk memanggil metode dari kelas super, Anda dapat menggunakan kata kunci super, tetapi jika Anda ingin membuatnya dengan antarmuka super, Anda harus menyebutkannya secara eksplisit.

class ParentClass {
    public void hello() {
        System.out.println("Hello ParentClass!");
    }
}

interface InterfaceFoo {
    default public void hello() {
        System.out.println("Hello InterfaceFoo!");
    }
}

interface InterfaceBar {
    default public void hello() {
        System.out.println("Hello InterfaceBar!");
    }
}

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super is wrong!)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }

    public static void main(String[] args) {
        new Example().hello();
    }
}

Keluaran:

Halo ParentClass!
Halo InterfaceFoo!
Halo InterfaceBar!

Dávid Horváth
sumber
3

Anda tidak perlu mengganti metode default suatu antarmuka. Sebut saja seperti berikut:

public class B implements A {

    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    public void afoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
       B b=new B();
       b.afoo();
    }
}

Keluaran:

A.foo

Masudul
sumber
9
OP mengatakan: "[apakah] mungkin untuk secara eksplisit memanggil implementasi standar dari suatu metode ketika metode itu telah ditimpa"
dasblinkenlight