Héritage Java à la volée


Soit ClassA une classe abstraite.

Je me demande s'il est possible de faire quelque chose comme ça en Java:

public static abstract class ClassA {
    abstract void foo();
}

private ClassB extends ClassA a = new ClassA() {
     // define abstract methods here
     foo() { System.out.println("in anon!"); }

     // define OTHER variables here
     public int varB = 10;
}

// later... varB is not defined in ClassA, but it is in a.
// how can I access varB from a?
System.out.println(a.varB);

Je veux faire une note spéciale: remarquez comment j'imprime varB. Disons que varB n'a PAS été défini dans ClassA, seulement dans la classe interne anonyme.

J'ai beaucoup de classes abstraites dans lesquelles je définis leurs méthodes abstraites à la volée lorsque je les crée. Cependant, je voudrais également traiter ces classes comme leur propre type parce que parfois j'ai besoin de accédez aux variables de cette classe qui sont spécifiques à cette version de l'objet.

Existe-t-il un moyen de faire quelque chose de similaire à ce que j'ai montré ci-dessus, ou dois-je créer un "ClassB" qui s'étend de "ClassA" à chaque fois?

Existe-t-il un type de solution de contournement?

Merci

Author: Luca, 2017-03-16

3 answers

Les classes anonymes ne conviendraient-elles pas à votre cas d'utilisation?

public static void main(String[] args) {
    // Make an anonymous instance of A
    final A first = new A() {
        private final int i = 10;

        void foo() {
            System.out.println(i);
        }
    };

    // Make another anonymous instance of A
    final A second = new A() {
        private final String message = "Listen!";

        void foo() {
            System.out.println("Hey!");
            System.out.println(message);
        }
    };

    // They do their own unique things
    first.foo();
    second.foo();

    // Both have A as a super-type
    System.out.println(first instanceof A);
    System.out.println(second instanceof A);

    // But first and second are *not* A and therefore not the same class!
    final boolean isSameClass = first.getClass().equals(second.getClass());
    System.out.println(isSameClass);
  }

  static abstract class A {
     abstract void foo();
  }

L'idée ici est que lorsque vous créez une nouvelle classe anonyme, vous sous-tapez en fait la classe que vous utilisez pour une seule instance. Cela fait partie de la raison pour laquelle les initialiseurs à double accolade sont une mauvaise idée!

EDIT: Accéder à une variable qui appartient uniquement à une classe anonyme n'est pas possible. Cependant, si vous êtes d'accord avec la réflexion, quelque chose comme ça pourrait fonctionner:

try {
    final Field i = first.getClass().getDeclaredField("i");
    i.setAccessible(true);
    System.out.println(i.getInt(first));
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

C'est joli désordonné et je ne le recommanderais pas nécessairement, mais il accomplit ce que vous vous apprêtez à faire ici.

 1
Author: mbStavola, 2017-05-23 12:32:08

Essayez Classes internes anonymes Java. échantillon comme ci-dessous:

abstract class ClassA {  
 abstract void eat();  
}  
class TestAnonymousInner{  
 public static void main(String args[]){  
  ClassA p=new ClassA (){  
    void eat(){System.out.println("nice fruits");}  
  };  
  p.eat();  
}  
}  

EDIT:

En ce qui concerne l'accès à la variable varA, vous devez déclarercette variable dans la classe abstraite , car ClassA a besoin des informations sur la variable. Ici, nous pouvons traiter objet référencé par p comme la classe enfant de ClassA {[11] } qui fait référence à la référence de son parent, et donc parent n'a pas accès aux méthodes et à la variable introduit dans la classe enfant( dans ce cas, la classe anonyme ).

 4
Author: VijayD, 2017-03-16 11:07:04

, Vous pouvez définir une nouvelle classe localement dans une méthode.

J'ai ajouté une nouvelle classe MixA dans la méthode main. Juste pour voir comment cela fonctionne, cette classe étend une classe abstraite ClassA et implémente une interface AInterface mais vous n'avez pas besoin de le faire, étend ou implémente simplement ce dont vous avez besoin.

Donc, étant donné que la classe est définie, vous pouvez au moment de la compilation trouver chaque méthode ou public que vous ajoutez:

abstract class ClassA {
  abstract void doThis();
}

interface AInterface {
  public int getInternalValue();
}

public class TestAnonymousInner {
  public static void main(String args[])
  {

     class MixA extends ClassA implements AInterface {

      public int varB = 10;

      @Override
      public int getInternalValue()
      {
        return 0;
      }

      @Override
      void doThis()
      {
      }

    }

    MixA b = new MixA();    
    b.getInternalValue();
    b.doThis();

    System.out.println(b.varB);

  }
}
 0
Author: freedev, 2017-03-16 08:44:36