Exercice de méta-programmation

Cet exercice est inspiré de http://www.devsource.com/c/a/Languages/An-Exercise-in-Metaprogramming-with-Ruby/ qui semble mort :(

Cet exercice est réalisable dans les langages à objets qui possèdent un méta-niveau. Dans la suite on utilise Ruby et Java comme langages cibles, mais Python et C# fonctionneraient aussi.

Savoir lire la doc est important, partez de ces classes pour trouver l'information utile.

Création d'instances par meta-programmation

Implémentez la méthode strinit qui prend une classe et une String et qui instancie cette classe avec les valeurs de la String qui sont séparées par des virgules.

Code initial en Ruby: meta1.rb

En Java: Meta1.java et Personne.java

Créations d'objets lus d'un fichier CSV

Implémentez la méthode csvinits qui prend un nom de fichier CSV et pour chaque ligne instancie un objet du fichier (en utilisant strinit).

  • La première ligne du fichier est ignorée (on l'utilisera plus tard).
  • Le nom de la classe à instancier est déduite du nom du fichier.

Le fichier personne.csv:

prenom,nom
Jon,Snow
Daenerys,Targaryen

En Ruby: meta2.rb

En Java: Meta2.java

Création de classe lue d'un fichier CSV

Ceci n'est pas réalisable directement en Java, mais est faisable en Ruby et Python.

Créez une méthode csvclass qui prend un nom de fichier CSV et retourne les instances d'une classe anonyme ainsi que la classe anonyme elle-même (retour multiple).

  • Important: vous devez créer une classe à partir de rien

La classe anonyme a les caractéristiques suivantes:

  • Il y a un accesseur en lecture (getter) pour chacun des champs du CSV. Le nom des champs est donné dans la première ligne du fichier.
  • Il y a un constructeur qui prend les arguments et les initialise dans l'ordre.

En Ruby: meta3.rb

Typage des champs

Ceci n'est pas réalisable directement en Ruby ou Python (pas de types statiques), mais est faisable en Java et C#.

Dans les exemples précédents, les champs de nos objets étaient tous de type String. Maintenant il faut convertir les champs dans les bons types.

Ce qui change:

  1. la classe doit avoir un constructeur public sans paramètre.
  2. pour chacun des champs foo du CSV il doit y avoir un setter setFoo dans la classe.
  3. le type du paramètre du setter détermine le comportement à adopter pour les champs:
    • si le type est String, le champ de l'objet doit être initialisé directement du CSV.
    • si le type est un type primitif, la valeur du champ doit être parsée (par exemple avec Integer.parseInt)
    • si le type est une autre classe, cette autre classe doit avoir un constructeur qui accepte un unique paramètre de type String.

Des données de bataille.csv:

nom,annee,decisive
Massacre à Durlieu,302 AC, true
Bataille de Chateau Noir, 301 AC, true
Bataille de Qohor, 100 BC, true
Bataille de Ironrath, 301 AC, false

En Java: Meta4.java, Bataille.java, Annee.java