t
t
t
t
t t 12) Identification dynamique de type
tttt
12) Identification dynamique de type
Texte original t Traducteur : Daniel LE BERRE
t
t
///
Ce chapitre contient 3 pages
1 2 3
\\\
t t t
t t t
t
t t t
There’s a rather narrow restriction on instanceof: you can compare it to a named type only, and not to a Class object. In the example above you might feel that it’s tedious to write out all of those instanceof expressions, and you’re right. But there is no way to cleverly automate instanceof by creating an ArrayList of Class objects and comparing it to those instead (stay tuned—you’ll see an alternative). This isn’t as great a restriction as you might think, because you’ll eventually understand that your design is probably flawed if you end up writing a lot of instanceof expressions. t Il existe cependant une limitation concernant instanceof : un objet peut être comparé à un identifiant de type, pas à un objet Class. Dans l'exemple précédent, vous pouvez trouver fastidieux d'écrire tous ces instanceof, et vous avez raison. Mais il n'y a pas moyen d'automatiser intelligemment le instanceof en créant un ArrayList d'objets Class et en comparant l'objet à ces derniers (nous verrons plus loin une alternative). Vous pouvez penser que ce n'est pas une très grande restriction, car vous finirez par comprendre que votre conception est mauvaise si vous finissez par écrire un grand nombre de instanceof.
t t t
Of course this example is contrived—you’d probably put a static data member in each type and increment it in the constructor to keep track of the counts. You would do something like that if you had control of the source code for the class and could change it. Since this is not always the case, RTTI can come in handy. t Bien sûr, cet exemple est imaginaire - vous utiliseriez probablement un attribut de classe (static) pour chaque type que vous incrémenteriez dans le constructeur pour mettre à jour les compteurs. Vous feriez cela si vous avez accès au code source de ces classes et pouvez le modifier. Comme ce n'est pas toujours le cas, le RTTI est bien pratique.
t t t

Using class literals

t

Utiliser les littéraux de classe

t t t
It’s interesting to see how the PetCount.java example can be rewritten using class literals. The result is cleaner in many ways: t Il est intéressant de voir comment l'exemple précédent PetCount.java peut être réécrit en utilisant les littéraux de classe. Le résultat est plus satisfaisant sur bien des points :
t t t
//: c12:PetCount2.java
// Using class literals.
import java.util.*;

public class PetCount2 {
  public static void main(String[] args)
  throws Exception {
    ArrayList pets = new ArrayList();
    Class[] petTypes = {
      // Class literals:
      Pet.class,
      Dog.class,
      Pug.class,
      Cat.class,
      Rodent.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // Offset by one to eliminate Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.add(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {
      System.err.println("Cannot instantiate");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Cannot access");
      throw e;
    }
    HashMap h = new HashMap();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.get(i);
      if(o instanceof Pet)
        ((Counter)h.get("class Pet")).i++;
      if(o instanceof Dog)
        ((Counter)h.get("class Dog")).i++;
      if(o instanceof Pug)
        ((Counter)h.get("class Pug")).i++;
      if(o instanceof Cat)
        ((Counter)h.get("class Cat")).i++;
      if(o instanceof Rodent)
        ((Counter)h.get("class Rodent")).i++;
      if(o instanceof Gerbil)
        ((Counter)h.get("class Gerbil")).i++;
      if(o instanceof Hamster)
        ((Counter)h.get("class Hamster")).i++;
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(pets.get(i).getClass());
    Iterator keys = h.keySet().iterator();
    while(keys.hasNext()) {
      String nm = (String)keys.next();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) +
        " quantity: " + cnt.i);
    }
  }
} ///:~
t
//: c12:PetCount2.java
// Utiliser les littéraux de classe.
import java.util.*;

public class PetCount2 {
  public static void main(String[] args)
  throws Exception {
    ArrayList pets = new ArrayList();
    Class[] petTypes = {
      // Littéraux de classe:
      Pet.class,
      Chien.class,
      Carlin.class,
      Chat.class,
      Rongeur.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // on ajoute 1 pour éliminer Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.add(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {
      System.err.println("Instantiation impossible");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Accès impossible");
      throw e;
    }
    HashMap h = new HashMap();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.get(i);
      if(o instanceof Pet)
        ((Counter)h.get("class Pet")).i++;
      if(o instanceof Chien)
        ((Counter)h.get("class Chien")).i++;
      if(o instanceof Carlin)
        ((Counter)h.get("class Carlin")).i++;
      if(o instanceof Chat)
        ((Counter)h.get("class Chat")).i++;
      if(o instanceof Rongeur)
        ((Counter)h.get("class Rongeur")).i++;
      if(o instanceof Gerbil)
        ((Counter)h.get("class Gerbil")).i++;
      if(o instanceof Hamster)
        ((Counter)h.get("class Hamster")).i++;
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(pets.get(i).getClass());
    Iterator keys = h.keySet().iterator();
    while(keys.hasNext()) {
      String nm = (String)keys.next();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) +
        " quantité: " + cnt.i);
    }
  }
} ///:~
t t t
Here, the typenames array has been removed in favor of getting the type name strings from the Class object. Notice that the system can distinguish between classes and interfaces. t Ici, le tableau typenames a été enlevé, on préfère obtenir de l'objet Class les chaînes identifiant les types. Notons que ce système permet au besoin de différencier classes et interfaces.
t t t
You can also see that the creation of petTypes does not need to be surrounded by a try block since it’s evaluated at compile-time and thus won’t throw any exceptions, unlike Class.forName( ). t On peut aussi remarquer que la création de petTypes ne nécessite pas l'utilisation d'un block try puisqu'il est évalué à la compilation et ne lancera donc aucune exception, contrairement à Class.forName().
t t t
When the Pet objects are dynamically created, you can see that the random number is restricted so it is between one and petTypes.length and does not include zero. That’s because zero refers to Pet.class, and presumably a generic Pet object is not interesting. However, since Pet.class is part of petTypes the result is that all of the pets get counted. t Quand les objets Pet sont créés dynamiquement, vous pouvez voir que le nombre aléatoire généré est compris entre un (ndt inclus) et petTypes.length (ndt exclus), donc ne peut pas prendre la valeur zéro. C'est parce que zéro réfère à Pet.class, et que nous supposons que créer un objet générique Pet n'est pas intéressant. Cependant, comme Pet.class fait partie de petTypes, le nombre total d'animaux familiers est compté.
t t t

A dynamic instanceof

t

Un instanceof dynamique

t t t
The Class isInstance method provides a way to dynamically call the instanceof operator. Thus, all those tedious instanceof statements can be removed in the PetCount example: t La méthode isInstance de Class fournit un moyen d'appeler dynamiquement l'opérateur instanceof. Ainsi, toutes ces ennuyeuses expressions instanceof peuvent être supprimées de l'exemple PetCount :
t t t
//: c12:PetCount3.java
// Using isInstance().
import java.util.*;

public class PetCount3 {
  public static void main(String[] args)
  throws Exception {
    ArrayList pets = new ArrayList();
    Class[] petTypes = {
      Pet.class,
      Dog.class,
      Pug.class,
      Cat.class,
      Rodent.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // Offset by one to eliminate Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.add(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {
      System.err.println("Cannot instantiate");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Cannot access");
      throw e;
    }
    HashMap h = new HashMap();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.get(i);
      // Using isInstance to eliminate individual
      // instanceof expressions:
      for (int j = 0; j < petTypes.length; ++j)
        if (petTypes[j].isInstance(o)) {
          String key = petTypes[j].toString();
          ((Counter)h.get(key)).i++;
        }
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(pets.get(i).getClass());
    Iterator keys = h.keySet().iterator();
    while(keys.hasNext()) {
      String nm = (String)keys.next();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) +
        " quantity: " + cnt.i);
    }
  }
} ///:~
t
//: c12:PetCount3.java
// Utiliser isInstance().
import java.util.*;

public class PetCount3 {
  public static void main(String[] args)
  throws Exception {
    ArrayList pets = new ArrayList();
    Class[] petTypes = {
      Pet.class,
      Chien.class,
      Carlin.class,
      Chat.class,
      Rongeur.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // Ajoute 1 pour éliminer Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.add(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {
      System.err.println("Instantiation impossible");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Accès impossible");
      throw e;
    }
    HashMap h = new HashMap();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.get(i);
      // Utiliser isInstance pour automatiser
      // l'utilisation des instanceof :
      // Ndt: Pourquoi ce ++j ????
      for (int j = 0; j < petTypes.length; ++j)
        if (petTypes[j].isInstance(o)) {
          String key = petTypes[j].toString();
          ((Counter)h.get(key)).i++;
        }
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(pets.get(i).getClass());
    Iterator keys = h.keySet().iterator();
    while(keys.hasNext()) {
      String nm = (String)keys.next();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) +
        " quantity: " + cnt.i);
    }
  }
} ///:~
t t t
You can see that the isInstance( ) method has eliminated the need for the instanceof expressions. In addition, this means that you can add new types of pets simply by changing the petTypes array; the rest of the program does not need modification (as it did when using the instanceof expressions). t On peut noter que l'utilisation de la méthode isInstance() a permis d'éliminer les expressions instanceof. De plus, cela signifie que de nouveaux types d'animaux familiers peuvent être ajoutés simplement en modifiant le tableau petTypes ; le reste du programme reste inchangé (ce qui n'est pas le cas lorsqu'on utilise des instanceof).
t t t

instanceof vs. Class equivalence

t

instanceof vs. équivalence de classe

t t t
When querying for type information, there’s an important difference between either form of instanceof (that is, instanceof or isInstance( ), which produce equivalent results) and the direct comparison of the Class objects. Here’s an example that demonstrates the difference: t Lorsque vous demandez une information de type, il y a une différence importante entre l'utilisation d'une forme de instanceof (instanceof ou isInstance(), qui produisent des résultats équivalents) et la comparaison directe des objets Class. Voici un exemple qui illustre cette différence :
t t t
//: c12:FamilyVsExactType.java
// The difference between instanceof and class

class Base {}
class Derived extends Base {}

public class FamilyVsExactType {
  static void test(Object x) {
    System.out.println("Testing x of type " +
      x.getClass());
    System.out.println("x instanceof Base " +
      (x instanceof Base));
    System.out.println("x instanceof Derived " +
      (x instanceof Derived));
    System.out.println("Base.isInstance(x) " +
      Base.class.isInstance(x));
    System.out.println("Derived.isInstance(x) " +
      Derived.class.isInstance(x));
    System.out.println(
      "x.getClass() == Base.class " +
      (x.getClass() == Base.class));
    System.out.println(
      "x.getClass() == Derived.class " +
      (x.getClass() == Derived.class));
    System.out.println(
      "x.getClass().equals(Base.class)) " +
      (x.getClass().equals(Base.class)));
    System.out.println(
      "x.getClass().equals(Derived.class)) " +
      (x.getClass().equals(Derived.class)));
  }
  public static void main(String[] args) {
    test(new Base());
    test(new Derived());
  }
} ///:~
t
//: c12:FamilyVsExactType.java
// La différence entre instanceof et class

class Base {}
class Derived extends Base {}

public class FamilyVsExactType {
  static void test(Object x) {
    System.out.println("Teste x de type " +
      x.getClass());
    System.out.println("x instanceof Base " +
      (x instanceof Base));
    System.out.println("x instanceof Derived " +
      (x instanceof Derived));
    System.out.println("Base.isInstance(x) " +
      Base.class.isInstance(x));
    System.out.println("Derived.isInstance(x) " +
      Derived.class.isInstance(x));
    System.out.println(
      "x.getClass() == Base.class " +
      (x.getClass() == Base.class));
    System.out.println(
      "x.getClass() == Derived.class " +
      (x.getClass() == Derived.class));
    System.out.println(
      "x.getClass().equals(Base.class)) " +
      (x.getClass().equals(Base.class)));
    System.out.println(
      "x.getClass().equals(Derived.class)) " +
      (x.getClass().equals(Derived.class)));
  }
  public static void main(String[] args) {
    test(new Base());
    test(new Derived());
  }
} ///:~
t t t
The test( ) method performs type checking with its argument using both forms of instanceof. It then gets the Class reference and uses == and equals( ) to test for equality of the Class objects. Here is the output: t La méthode test() effectue une vérification du type de son argument en utilisant les deux formes de instanceof. Elle récupère ensuite la référence sur l'objet Class et utilise == et equals() pour tester l'égalité entre les objets Class. Le résultat est le suivant :
t t t
Testing x of type class Base
x instanceof Base true
x instanceof Derived false
Base.isInstance(x) true
Derived.isInstance(x) false
x.getClass() == Base.class true
x.getClass() == Derived.class false
x.getClass().equals(Base.class)) true
x.getClass().equals(Derived.class)) false
Testing x of type class Derived
x instanceof Base true
x instanceof Derived true
Base.isInstance(x) true
Derived.isInstance(x) true
x.getClass() == Base.class false
x.getClass() == Derived.class true
x.getClass().equals(Base.class)) false
x.getClass().equals(Derived.class)) true
t
Teste x de type class Base
x instanceof Base true
x instanceof Derived false
Base.isInstance(x) true
Derived.isInstance(x) false
x.getClass() == Base.class true
x.getClass() == Derived.class false
x.getClass().equals(Base.class)) true
x.getClass().equals(Derived.class)) false
Teste x de type class Derived
x instanceof Base true
x instanceof Derived true
Base.isInstance(x) true
Derived.isInstance(x) true
x.getClass() == Base.class false
x.getClass() == Derived.class true
x.getClass().equals(Base.class)) false
x.getClass().equals(Derived.class)) true
t t t
Reassuringly, instanceof and isInstance( ) produce exactly the same results, as do equals( ) and ==. But the tests themselves draw different conclusions. In keeping with the concept of type, instanceof says “are you this class, or a class derived from this class?” On the other hand, if you compare the actual Class objects using ==, there is no concern with inheritance—it’s either the exact type or it isn’t. t Il est rassurant de constater que instanceof et isIntance() produisent des résultats identiques, de même que equals() et ==. Mais les tests eux-mêmes aboutissent à  des conclusions différentes. instanceof teste le concept de type et signifie « es-tu de cette classe, ou d'une classe dérivée ? ». Autrement, si on compare les objets Class en utilisant ==, il n'est plus question d'héritage - l'objet est de ce type ou non.
t t t

RTTI syntax

t

La syntaxe du RTTI

t t t
Java performs its RTTI using the Class object, even if you’re doing something like a cast. The class Class also has a number of other ways you can use RTTI. t Java effectue son identification dynamique de type (RTTI) à l'aide de l'objet Class, même lors d'un transtypage. La classe Class dispose aussi de nombreuses autres manières d'être utilisée pour le RTTI.
t t t
First, you must get a reference to the appropriate Class object. One way to do this, as shown in the previous example, is to use a string and the Class.forName( ) method. This is convenient because you don’t need an object of that type in order to get the Class reference. However, if you do already have an object of the type you’re interested in, you can fetch the Class reference by calling a method that’s part of the Object root class: getClass( ). This returns the Class reference representing the actual type of the object. Class has many interesting methods, demonstrated in the following example: t Premièrement, il faut obtenir une référence sur l'objet Class approprié. Une manière de le faire, comme nous l'avons vu dans l'exemple précédent, est d'utiliser une chaîne de caractères et la méthode Class.forName(). C'est très pratique car il n'est pas nécessaire d'avoir un objet de ce type pour obtenir la référence sur l'objet Class. Néanmoins, si vous avez déjà un objet de ce type, vous pouvez retrouver la référence à l'objet Class en appelant une méthode qui appartient à la classe racine ObjectgetClass(). Elle retourne une référence sur l'objet Class représentant le type actuel de l'objet. Class a de nombreuses méthodes intéressantes, comme le montre l'exemple suivant :
t t t
//: c12:ToyTest.java
// Testing class Class.

interface HasBatteries {}
interface Waterproof {}
interface ShootsThings {}
class Toy {
  // Comment out the following default
  // constructor to see
  // NoSuchMethodError from (*1*)
  Toy() {}
  Toy(int i) {}
}

class FancyToy extends Toy
    implements HasBatteries,
      Waterproof, ShootsThings {
  FancyToy() { super(1); }
}

public class ToyTest {
  public static void main(String[] args)
  throws Exception {
    Class c = null;
    try {
      c = Class.forName("FancyToy");
    } catch(ClassNotFoundException e) {
      System.err.println("Can't find FancyToy");
      throw e;
    }
    printInfo(c);
    Class[] faces = c.getInterfaces();
    for(int i = 0; i < faces.length; i++)
      printInfo(faces[i]);
    Class cy = c.getSuperclass();
    Object o = null;
    try {
      // Requires default constructor:
      o = cy.newInstance(); // (*1*)
    } catch(InstantiationException e) {
      System.err.println("Cannot instantiate");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Cannot access");
      throw e;
    }
    printInfo(o.getClass());
  }
  static void printInfo(Class cc) {
    System.out.println(
      "Class name: " + cc.getName() +
      " is interface? [" +
      cc.isInterface() + "]");
  }
} ///:~
t
//: c12:ToyTest.java
// Teste la classe Class.

interface HasBatteries {}
interface Waterproof {}
interface ShootsThings {}
class Toy {
  // Commenter le constructeur par
  // défault suivant pour obtenir
  // NoSuchMethodError depuis (*1*)
  Toy() {}
  Toy(int i) {}
}

class FancyToy extends Toy
    implements HasBatteries,
      Waterproof, ShootsThings {
  FancyToy() { super(1); }
}

public class ToyTest {
  public static void main(String[] args)
  throws Exception {
    Class c = null;
    try {
      c = Class.forName("FancyToy");
    } catch(ClassNotFoundException e) {
      System.err.println("Ne trouve pas FancyToy");
      throw e;
    }
    printInfo(c);
    Class[] faces = c.getInterfaces();
    for(int i = 0; i < faces.length; i++)
      printInfo(faces[i]);
    Class cy = c.getSuperclass();
    Object o = null;
    try {
      // Nécessite un constructeur par défaut :
      o = cy.newInstance(); // (*1*)
    } catch(InstantiationException e) {
      System.err.println("Instanciation impossible");
      throw e;
    } catch(IllegalAccessException e) {
      System.err.println("Accès impossible");
      throw e;
    }
    printInfo(o.getClass());
  }
  static void printInfo(Class cc) {
    System.out.println(
      "Class nom: " + cc.getName() +
      " est une interface ? [" +
      cc.isInterface() + "]");
  }
} ///:~
t t t
You can see that class FancyToy is quite complicated, since it inherits from Toy and implements the interfaces of HasBatteries, Waterproof, and ShootsThings. In main( ), a Class reference is created and initialized to the FancyToy Class using forName( ) inside an appropriate try block. t On peut voir que la classe FancyToy est assez compliquée, puisqu'elle hérite de Toy et implémente les interfaces HasBatteries, Waterproof et ShootThings. Dans main(), une référence de Class est créée et initialisée pour la classe FancyToy en utilisant forName() à l'intérieur du block try approprié.
t t t
The Class.getInterfaces( ) method returns an array of Class objects representing the interfaces that are contained in the Class object of interest. t La méthode Class.getInterfaces() retourne un tableau d'objets Class représentant les interfaces qui sont contenues dans l'objet en question.
t t t
If you have a Class object you can also ask it for its direct base class using getSuperclass( ). This, of course, returns a Class reference that you can further query. This means that, at run-time, you can discover an object’s entire class hierarchy. t Si vous avez un objet Class, vous pouvez aussi lui demander la classe dont il hérite directement en utilisant la méthode getSuperclass(). Celle-ci retourne, bien sûr, une référence de Class que vous pouvez interroger plus en détail. Cela signifie qu'à l'éxécution, vous pouvez découvrir la hiérarchie de classe complète d'un objet.
t t t
The newInstance( ) method of Class can, at first, seem like just another way to clone( ) an object. However, you can create a new object with newInstance( ) without an existing object, as seen here, because there is no Toy object—only cy, which is a reference to y’s Class object. This is a way to implement a “virtual constructor,” which allows you to say “I don’t know exactly what type you are, but create yourself properly anyway.” In the example above, cy is just a Class reference with no further type information known at compile-time. And when you create a new instance, you get back an Object reference. But that reference is pointing to a Toy object. Of course, before you can send any messages other than those accepted by Object, you have to investigate it a bit and do some casting. In addition, the class that’s being created with newInstance( ) must have a default constructor. In the next section, you’ll see how to dynamically create objects of classes using any constructor, with the Java reflection API. t La méthode newInstance() de Class peut, au premier abord, ressembler à un autre moyen de cloner() un objet. Néanmoins, vous pouvez créer un nouvel objet avec newInstance() sans un objet existant, comme nous le voyons ici, car il n'y a pas d'objets Toy - seulement cy qui est une référence sur l'objet Class de y. C'est un moyen de construire un « constructeur virtuel », qui vous permet d'exprimer « je ne sais pas exactement de quel type vous êtes, mais créez-vous proprement ». Dans l'exemple ci-dessus, cy est seulement une référence sur Class sans aucune autre information à la compilation. Et lorsque vous créez une nouvelle instance, vous obtenez une référence sur un Object. Mais cette référence pointe sur un objet Toy. Bien entendu, avant de pouvoir envoyer d'autres messages que ceux acceptés par Object, vous devez l'examiner un peu plus et effectuer quelques transtypages. De plus, la classe de l'objet créé par newInstance() doit avoir un constructeur par défaut. Dans la prochaine section, nous verrons comment créer dynamiquement des objets de classes utilisant n'importe quel constructeur, avec l'API de réflexion Java.
t t t
The final method in the listing is printInfo( ), which takes a Class reference and gets its name with getName( ), and finds out whether it’s an interface with isInterface( ). t La dernière méthode dans le listing est printInfo(), qui prend en paramètre une référence sur Class, récupère son nom avec getName(), et détermine si c'est une interface avec isInterface().
t t t
The output from this program is: t Le résultat de ce programme est :
t t t
Class name: FancyToy is interface? [false]
Class name: HasBatteries is interface? [true]
Class name: Waterproof is interface? [true]
Class name: ShootsThings is interface? [true]
Class name: Toy is interface? [false]
t
Class nom: FancyToy est une interface ? [false]
Class nom: HasBatteries est une interface ? [true]
Class nom: Waterproof est une interface ? [true]
Class nom: ShootsThings est une interface ? [true]
Class nom: Toy est une interface ? [false]
t t t
Thus, with the Class object you can find out just about everything you want to know about an object. t Ainsi, avec l'objet Class, vous pouvez découvrir vraiment tout ce que vous voulez savoir sur un objet.
t t t

Reflection: run-time class information

t

Réflexion : information de classe dynamique 

t t t
If you don’t know the precise type of an object, RTTI will tell you. However, there’s a limitation: the type must be known at compile-time in order for you to be able to detect it using RTTI and do something useful with the information. Put another way, the compiler must know about all the classes you’re working with for RTTI. t Si vous ne connaissez pas le type précis d'un objet, le RTTI vous le dira. Néanmoins, il y a une limitation : le type doit être connu à la compilation afin que vous puissiez le détecter en utilisant le RTTI et faire quelque chose d'intéressant avec cette information. Autrement dit, le compilateur doit connaître toutes les classes que vous utilisez pour le RTTI.
t t t
This doesn’t seem like that much of a limitation at first, but suppose you’re given a reference to an object that’s not in your program space. In fact, the class of the object isn’t even available to your program at compile-time. For example, suppose you get a bunch of bytes from a disk file or from a network connection and you’re told that those bytes represent a class. Since the compiler can’t know about the class while it’s compiling the code, how can you possibly use such a class? t Ceci peut ne pas paraître une grande limitation à première vue, mais supposons que l'on vous donne une référence sur un objet qui n'est pas dans l'espace de votre programme. En fait, la classe de l'objet n'est même pas disponible lors de la compilation. Par exemple, supposons que vous récupériez un paquet d'octets à partir d'un fichier sur disque ou via une connexion réseau et que l'on vous dise que ces octets représentent une classe. Puisque le compilateur ne peut pas connaître la classe lorsqu'il compile le code, comment pouvez vous utilisez cette classe ?
t t t
In a traditional programming environment this seems like a far-fetched scenario. But as we move into a larger programming world there are important cases in which this happens. The first is component-based programming, in which you build projects using Rapid Application Development (RAD) in an application builder tool. This is a visual approach to creating a program (which you see on the screen as a “form”) by moving icons that represent components onto the form. These components are then configured by setting some of their values at program time. This design-time configuration requires that any component be instantiable, that it exposes parts of itself, and that it allows its values to be read and set. In addition, components that handle GUI events must expose information about appropriate methods so that the RAD environment can assist the programmer in overriding these event-handling methods. Reflection provides the mechanism to detect the available methods and produce the method names. Java provides a structure for component-based programming through JavaBeans (described in Chapter 13). t Dans un environnement de travail traditionnel cela peut sembler un scénario improbable. Mais dès que l'on se déplace dans un monde de la programmation plus vaste, il y a des cas importants dans lesquels cela arrive. Le premier est la programmation par composants, dans lequel vous construisez vos projets en utilisant le Rapid Application Development (RAD) dans un constructeur d'application. C'est une approche visuelle pour créer un programme (que vous voyez à l'écran comme un « formulaire » (form)) en déplaçant des icônes qui représentent des composants dans le formulaire. Ces composants sont alors configurés en fixant certaines de leurs valeurs. Cette configuration durant la conception nécessite que chacun des composants soit instanciable, qu'il dévoile une partie de lui-même et qu'il permette que ses valeurs soient lues et fixées. De plus, les composants qui gèrent des événements dans une GUI doivent dévoiler des informations à propos des méthodes appropriées pour que l'environnement RAD puisse aider le programmeur à redéfinir ces méthodes de gestion d'événements. La réflexion fournit le mécanisme pour détecter les méthodes disponibles et produire leurs noms. Java fournit une structure de programmation par composants au travers de JavaBeans (décrit dans le chapitre 13).
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel