231 votes

Accès au constructeur d'une classe anonyme

Supposons que je dispose d'une classe concrète Class1 et que je crée une classe anonyme à partir de celle-ci.

Object a = new Class1(){
        void someNewMethod(){
        }
      };

Est-il possible de surcharger le constructeur de cette classe anonyme ? Comme indiqué ci-dessous

Object a = new Class1(){
        void someNewMethod(){
        }
        public XXXXXXXX(int a){
          super();
          System.out.println(a);
        }
      };

Avec quelque chose à xxxxxxxx pour nommer le constructeur ?

7 votes

Il vaut la peine d'être lu DoubleBraceInitialisation

0 votes

Si le parent a un constructeur : stackoverflow.com/questions/20807148/

305voto

Jon Skeet Points 692016

Desde el Spécification du langage Java , section 15.9.5.1 :

Une classe anonyme explicitement déclaré.

Désolé :(

EDIT : Comme alternative, vous pouvez créer quelques variables locales finales, et/ou inclure un initialisateur d'instance dans la classe anonyme. Par exemple, vous pouvez créer des variables locales finales et/ou inclure un initialisateur d'instance dans la classe anonyme :

public class Test {
    public static void main(String[] args) throws Exception {
        final int fakeConstructorArg = 10;

        Object a = new Object() {
            {
                System.out.println("arg = " + fakeConstructorArg);
            }
        };
    }
}

C'est grotesque, mais cela pourrait vous aider. Sinon, utilisez une classe imbriquée correcte :)

18 votes

Arne, je le crois, il ne l'a pas copié. Il connaît suffisamment Java pour être juste et donner le crédit quand il l'aurait copié, je pense.

25 votes

OMG, est-ce que quelqu'un a reproché au Jon Skeet d'avoir copié ?

0 votes

Comment pourrais-je appeler une méthode de la superclasse Test à partir de println, alors que cette méthode est surchargée ?

107voto

Arne Burmeister Points 8423

Ce n'est pas possible, mais vous pouvez ajouter un initialisateur anonyme comme ceci :

final int anInt = ...;
Object a = new Class1()
{
  {
    System.out.println(anInt);
  }

  void someNewMethod() {
  }
};

N'oubliez pas final sur les déclarations des variables locales ou des paramètres utilisés par la classe anonyme, comme je l'ai fait pour anInt.

0 votes

C'est en fait très proche d'un constructeur. Je peux accéder aux membres protégés d'une classe de base abstraite. Tout le reste peut être fait dans le code avant l'instanciation de la classe anonyme.

82voto

Joel Points 1081

Voici une autre façon de contourner le problème :

public class Test{

    public static final void main(String...args){

        new Thread(){

            private String message = null;

            Thread initialise(String message){

                this.message = message;
                return this;
            }

            public void run(){
                System.out.println(message);
            }
        }.initialise(args[0]).start();
    }
}

22 votes

Belle solution, mais l'utilisation de Thread ici la rend quelque peu trompeuse au premier abord (pendant un moment, j'ai cru que l'on créait un thread séparé pour initialiser les choses !)

8 votes

Il convient de noter qu'après t est défini, vous ne pouvez pas appeler t.initialise() sauf si cette fonction est définie dans le type de classe/interface.

1 votes

@AramKocharyan Cela le fait fonctionner encore plus comme un constructeur.

20voto

Black Panther Points 1603

Je sais que le fil de discussion est trop vieux pour que l'on puisse y répondre. Mais je pense que cela vaut la peine.

Bien que vous ne puissiez pas avoir de constructeur explicite, si votre intention est d'appeler un constructeur, éventuellement protégé, de la super-classe, vous n'avez qu'à faire ce qui suit.

StoredProcedure sp = new StoredProcedure(datasource, spName) {
    {// init code if there are any}
};

Voici un exemple de création d'un StoredProcedure dans Spring en passant un objet DataSource et un String objet.

En résumé, si vous souhaitez créer une classe anonyme et appeler le constructeur de la super-classe, créez la classe anonyme avec une fonction signature correspondant au constructeur de la super classe .

3voto

Peter Verhas Points 51

Vous pouvez avoir un constructeur dans la classe abstraite qui accepte les paramètres init. La spécification Java précise seulement que la classe anonyme, qui est la descendance de la classe abstraite (facultativement) ou de l'implémentation d'une interface, ne peut pas avoir de constructeur de son propre chef.

Ce qui suit est tout à fait légal et possible :

static abstract class Q{
    int z;
    Q(int z){ this.z=z;}
    void h(){
        Q me = new Q(1) {
        };
    }
}

Si vous avez la possibilité d'écrire la classe abstraite vous-même, mettez-y un tel constructeur et utilisez l'API fluide lorsqu'il n'y a pas de meilleure solution. Vous pouvez ainsi surcharger le constructeur de votre classe originale en créant une classe sœur nommée avec un constructeur avec des paramètres et l'utiliser pour instancier votre classe anonyme.

0 votes

(raison d'être des classes anonymes) Comment avoir ce code dans une fonction ?

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