Dziedziczenie wielokrotne dla klasy anonimowej

98

W jaki sposób anonimowa klasa może implementować dwa (lub więcej) interfejsy? Alternatywnie, w jaki sposób może zarówno rozszerzyć klasę, jak i zaimplementować interfejs? Na przykład chcę utworzyć obiekt klasy anonimowej, który rozszerza dwa interfejsy:

    // Java 10 "var" is used since I don't know how to specify its type
    var lazilyInitializedFileNameSupplier = (new Supplier<String> implements AutoCloseable)() {
        private String generatedFileName;
        @Override
        public String get() { // Generate file only once
            if (generatedFileName == null) {
              generatedFileName = generateFile();
            }
            return generatedFileName;
        }
        @Override
        public void close() throws Exception { // Clean up
            if (generatedFileName != null) {
              // Delete the file if it was generated
              generatedFileName = null;
            }
        }
    };

Następnie mogę go użyć w bloku try-with-resources AutoCloseablejako leniwie zainicjowaną klasą narzędziową:

        try (lazilyInitializedFileNameSupplier) {
            // Some complex logic that might or might not 
            // invoke the code that creates the file
            if (checkIfNeedToProcessFile()) {
                doSomething(lazilyInitializedFileNameSupplier.get());
            }
            if (checkIfStillNeedFile()) {
                doSomethingElse(lazilyInitializedFileNameSupplier.get());
            }
        } 
        // By now we are sure that even if the file was generated, it doesn't exist anymore

Nie chcę, aby utworzyć klasę wewnętrzną, ponieważ jestem absolutnie pewien, że ta klasa nie zostaną wykorzystane w dowolnym miejscu z wyjątkiem metody muszę używać go w (i ja też może chcieć użyć zmienne lokalne zadeklarowane w tej metodzie, która może być vartypowym).

izogfif
źródło
Niestety, musisz sprawić, by konstruktor był widoczny w miejscach, w których inaczej by nie było.
Sridhar Sarnobat

Odpowiedzi:

99

Klasy anonimowe muszą coś rozszerzać lub implementować, jak każda inna klasa Javy, nawet jeśli jest to zwykłe java.lang.Object.

Na przykład:

Runnable r = new Runnable() {
   public void run() { ... }
};

Oto robiekt anonimowej klasy, która implementuje Runnable.

Klasa anonimowa może rozszerzyć inną klasę przy użyciu tej samej składni:

SomeClass x = new SomeClass() {
   ...
};

Nie możesz zaimplementować więcej niż jednego interfejsu. Aby to zrobić, potrzebujesz nazwanej klasy. Ani anonimowa klasa wewnętrzna, ani nazwana klasa nie mogą jednak rozszerzać więcej niż jednej klasy.

skaffman
źródło
1
Myślę, że drugie wyrażenie nie jest poprawne. Zadeklarowałeś już nazwę klasy jako SomeClass, nie jest już anonimowa. Sprawdź ten link docstore.mik.ua/orelly/java-ent/jnut/ch03_12.htm Kiedy „nowy” interfejs, anonimowa klasa jest tworzona przez rozszerzenie klasy „Object” i zaimplementowanie tego interfejsu. Ale podczas „tworzenia nowej” klasy z pierwszym napisanym wyrażeniem, klasa anonimowa (w rzeczywistości jest to instancja tej klasy anonimowej) zostanie utworzona przez rozszerzenie tej klasy.
lixiang
8
@youmiss: drugie wyrażenie utworzy instancję anonimowej klasy, która się rozszerza SomeClass. Ze względu na rozszerzenie domeny nadal jest anonimowe {...}.
skaffman
1
Rozumiem, przeoczyłem {...}.
lixiang
36

Klasa anonimowa zazwyczaj implementuje interfejs:

new Runnable() { // implements Runnable!
   public void run() {}
}

JFrame.addWindowListener( new WindowAdapter() { // extends  class
} );

Jeśli masz na myśli, czy możesz zaimplementować 2 lub więcej interfejsów, to myślę, że nie jest to możliwe. Następnie możesz utworzyć prywatny interfejs, który łączy oba. Chociaż nie mogę sobie łatwo wyobrazić, dlaczego chciałbyś, aby anonimowe zajęcia miały to:

 public class MyClass {
   private interface MyInterface extends Runnable, WindowListener { 
   }

   Runnable r = new MyInterface() {
    // your anonymous class which implements 2 interaces
   }

 }
extraneon
źródło
Podoba mi się ta odpowiedź, ponieważ jest przyjazna dla Google dla osób, które chcą zaimplementować 2 lub więcej interfejsów w innej implementacji.
L. Holanda,
16

Klasy anonimowe zawsze rozszerzają nadklasę lub implementują interfejsy. na przykład:

button.addActionListener(new ActionListener(){ // ActionListener is an interface
    public void actionPerformed(ActionEvent e){
    }
});

Co więcej, chociaż klasa anonimowa nie może implementować wielu interfejsów, możesz utworzyć interfejs, który rozszerza inny interfejs i pozwolić swojej anonimowej klasie na jego implementację.

MByD
źródło
13

Chyba nikt nie zrozumiał pytania. Wydaje mi się, że ten facet chciał czegoś takiego:

return new (class implements MyInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }
});

ponieważ pozwoliłoby to na takie rzeczy, jak wiele implementacji interfejsu:

return new (class implements MyInterface, AnotherInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }

    @Override
    public void anotherInterfaceMethod() { /*do something*/ }
});

byłoby to naprawdę miłe; ale to nie jest dozwolone w Javie .

Co można zrobić, to użyć lokalnych klas wewnątrz metody bloków:

public AnotherInterface createAnotherInterface() {
    class LocalClass implements MyInterface, AnotherInterface {
        @Override
        public void myInterfaceMethod() { /*do something*/ }

        @Override
        public void anotherInterfaceMethod() { /*do something*/ }
    }
    return new LocalClass();
}
thiagoh
źródło
Dokładnie, to właśnie zamierzał OP IMHO
DanielCuadra
pokazując kciuki za odpowiedź na zadane pytanie. co jest normalne na SO, że ludzie lubią odpowiadać, o co należy zapytać, a nie o to, o co zostało zapytane.
mfaisalhyder
3
// The interface
interface Blah {
    void something();
}

...

// Something that expects an object implementing that interface
void chewOnIt(Blah b) {
    b.something();
}

...

// Let's provide an object of an anonymous class
chewOnIt(
    new Blah() {
        @Override
        void something() { System.out.println("Anonymous something!"); }
    }
);
Oliver Charlesworth
źródło
1

Anonimowa klasa rozszerza się lub implementuje podczas tworzenia swojego obiektu Na przykład:

Interface in = new InterFace()
{

..............

}

Tutaj klasa anonimowa implementuje Interface.

Class cl = new Class(){

.................

}

tutaj Klasa anonimowa rozszerza klasę abstrakcyjną.

trapedInBatcaveWithBAtman
źródło
Nie widzę różnicy. Jak twój jest inny niż mój.
trapedInBatcaveWithBAtman
ładne i zwarte, w odpowiedzi brakuje mi słów „zawsze” lub „trzeba” :)
kiedysktos