Java'da açıkça varsayılan bir yöntemi çağırma


247

Java 8, mevcut uygulamaları değiştirmeye gerek kalmadan arabirimleri genişletme yeteneği sağlamak için varsayılan yöntemler sunar.

Bu yöntem geçersiz kılındığında veya farklı arabirimlerdeki çakışan varsayılan uygulamalar nedeniyle kullanılabilir olmadığında, bir yöntemin varsayılan uygulanmasını açıkça çağırmanın mümkün olup olmadığını merak ediyorum.

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?
    }
}

Yukarıdaki kod göz önüne alındığında, A.foo()B sınıfı bir yöntemden nasıl çağırırsınız ?


Neden A arayüzü içindeki foo () yönteminize uygulandığını söyleyebilir misiniz?
Maciej Cygan

20
@MaciejCygan Java 8'e izin verildi
Rohit Jain

Yanıtlar:


330

Gereğince bu makalede Arayüzde varsayılan yöntemi erişmek Akullanılarak

A.super.foo();

Bu aşağıdaki gibi kullanılabilir (arayüzlerin Ave Cher ikisinin de varsayılan yöntemleri olduğu varsayılarak 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
    }
}

Ave Cher ikisinde de .foo()yöntemler olabilir ve belirli bir varsayılan uygulama seçilebilir veya yeni foo()yönteminizin bir parçası olarak birini (veya her ikisini) kullanabilirsiniz . Uygulama sınıfınızdaki diğer yöntemlerde varsayılan sürümlere erişmek için de aynı sözdizimini kullanabilirsiniz.

Yöntem çağırma sözdiziminin resmi açıklaması JLS'nin 15. bölümünde bulunabilir .


14
Ayrıca, eğer dikkat A extends SomeOtherInterfaceve SomeOtherInterfacegelmiştir default Type method(), o zaman sadece arayamazsınız SomeOtherInterface.super.method()ChildClass dan. Üst arabirimlerin yöntemlerini değil , yalnızca ChildClass' implementsyan tümcesinde numaralandırılmış arabirimlerin varsayılan yöntemlerini çağırabilirsiniz .
gvlasov

1
@Suseika iyi bir nokta, aynı yok super.super.someMethod();(çünkü bu korkunç olurdu)
Richard Tingle

@gvlasov iyi bir nokta, ancak bir alt arabirimden bir üst arabirimin varsayılan yöntemine nasıl erişilir, mümkün mü ?? Güncelleme .......... Evet Mümkün, burada daha somut bir açıklama stackoverflow.com/a/24280376/3791156
Raaghu

@RichardTingle kusursuz cevap!
gaurav

17

Aşağıdaki kod çalışmalıdır.

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");
    }
}

Çıktı:

B.foo
A.foo

Bence bu yukarıdaki soruyu tanımlayan en iyi örnek. Teşekkürler
Hemanth Peela

8

Bu cevap esas olarak kapalı 45047550 sorusundan gelen kullanıcılar için yazılmıştır .

Java 8 arayüzleri çoklu kalıtımın bazı yönlerini ortaya koyar. Varsayılan yöntemlerin uygulanmış bir işlev gövdesi vardır. Süper sınıftan bir yöntemi çağırmak için anahtar kelimeyi kullanabilirsiniz super, ancak bunu süper bir arayüzle yapmak istiyorsanız, açıkça adlandırmanız gerekir.

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();
    }
}

Çıktı:

Merhaba ParentClass!
Merhaba InterfaceFoo!
Merhaba InterfaceBar!


3

Bir arabirimin varsayılan yöntemini geçersiz kılmanıza gerek yoktur. Sadece şu şekilde çağırın:

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();
    }
}

Çıktı:

A.foo


9
OP diyor ki: "Bu yöntem geçersiz kılındığında bir yöntemin varsayılan uygulamasını açıkça çağırmak mümkündür"
dasblinkenlight
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.