100 votes

Héritage multiple pour une classe anonyme

Comment une classe anonyme peut-elle implémenter deux interfaces (ou plus) ? Alternativement, comment peut-elle les deux étendre une classe et implémenter une interface ? Par exemple, je veux créer un objet de classe anonyme qui étend deux interfaces :

    // 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;
            }
        }
    };

Je peux ensuite l'utiliser dans un bloc try-with-resources comme suit AutoCloseable comme classe utilitaire initialisée paresseusement :

        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

Je ne veux pas créer une classe interne parce que je suis absolument sûr que cette classe ne sera pas utilisée ailleurs que dans la méthode dans laquelle j'ai besoin de l'utiliser (et j'ai aussi pourrait voulez utiliser les variables locales déclarées dans cette méthode qui pourraient être de var type).

102voto

skaffman Points 197885

Classes anonymes doit étendre ou implémenter quelque chose, comme n'importe quelle autre classe Java, même si c'est seulement java.lang.Object .

Par exemple :

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

Ici, r est un objet d'une classe anonyme qui implémente Runnable .

Une classe anonyme peut étendre une autre classe en utilisant la même syntaxe :

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

Ce que vous ne pouvez pas faire, c'est implémenter plus d'une interface. Vous avez besoin d'une classe nommée pour le faire. Cependant, ni une classe interne anonyme, ni une classe nommée ne peuvent étendre plus d'une classe.

37voto

extraneon Points 13362

Une classe anonyme implémente généralement une interface :

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

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

Si vous voulez savoir si vous pouvez mettre en œuvre 2 ou plusieurs interfaces, alors je pense que ce n'est pas possible. Vous pouvez alors créer une interface privée qui combine les deux. Bien que je ne puisse pas facilement imaginer pourquoi vous voudriez qu'une classe anonyme ait cela :

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

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

 }

16voto

MByD Points 78505

Classes anonymes toujours étendre la superclasse ou implémenter des interfaces. par exemple :

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

De plus, bien que la classe anonyme ne puisse pas implémenter plusieurs interfaces, vous pouvez créer une interface qui étend une autre interface et laisser votre classe anonyme l'implémenter.

15voto

thiagoh Points 1437

Je suppose que personne n'a compris la question. Je suppose que ce que ce type voulait était quelque chose comme ça :

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

car cela permettrait des choses comme les implémentations multiples d'interfaces :

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

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

ce serait vraiment bien, mais qui n'est pas autorisé en Java .

Ce que vous peut faire est utiliser classes locales à l'intérieur des blocs de méthodes :

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

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

3voto

Oli Charlesworth Points 148744
// 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!"); }
    }
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X