Les sources de la solution sont disponibles [ ici ].

Les commentaires :


sur l'abstraction

  • comme indiqué dans l'énoncé, il faut rendre abstrait les méthodes dont le code ne peut être défini au niveau de Humain, à savoir :
    • rencontre()
    • isHomme()
    • isFemme()
    • isGarcon()
    • isFille()

 

  • A noter que, comme dans le TD sur les équidé, cette abstraction n'est pas obligatoire et l'on peut parfaitement "tordre" le modèle pour que ces méthodes renvoient une valeur par défaut et que si ces valeurs par défaut ne conviennent pas dans les sous-classes, on redéfinit la méthode.
  • C'est par exemple ce que l'on pourrait faire avec les 4 méthodes isXXX(), en leur faisant retourner false dans Humain, et en redéfinissant une seule fois dans chaque sous-classe. Cela fait moins de code à écrire.
 

Classement avec expression lambda


  • Pour éviter de faire les 5 tris demandés à la fin d'un tour de jeu, la méthode trier() de Population a un paramètre indiquant le type de tri.
  • Comme on peut le constater avec le dernier tri, l'EL peut rapidement devenir assez longue, ce qui a tendance à nuire à la lisibilité du code. C'est aussi une raison pour que ce tri soit mis dans une méthode à part dans Population, au lieu de se trouver en plein milieu du code du moteur de jeu.
  • On remarque également dans ces tris l'astuce qui consiste à transformer le type des humains passer en paramètre de l'EL en un entier valant 0 ou 1. Cela évite de faire des tests "compliqué" à base de isHomme(), isFemme() etc.

Création d'interface fonctionnelles.

 

- prendre du poids en vieillissant

  • NB 1 : Dans la solution, l'IF Aging a comme méthode apply() au lieu de gainWeight(), ce qui ne change rien à la mise en place de la solution.
  • NB 2 : Comme l'EL doit faire utiliser l'âge et manipuler le poids, il faut ajouter des getters/setters pour âge et poids dans Humain.

 

  • La méthode vieillir() de population permet d'appeler la méthode vieillir() sur chaque humain. A l'exécution, on va donc appeler la méthode des instances réelles de ces humains, donc celle de Homme, Femme (+Garcon/Fille)
  • Par conséquent, si ces méthodes ont en paramètre une EL pour faire grossir, il faut que l'EL soit écrite pour convenir aussi bien a une instance d'Homme que de Femme.
  • C'est pourquoi l'EL qui est définie dans LifeGame, comme paramètre de vieillir() de Population, commence par tester si l'humain en paramètre est masculin ou féminin.

 

  • Cette façon d'écrire l'EL implique une chose : si le code fonctionne aussi bien pour un Homme qu'une Femme, alors l'appel à la méthode apply() peut très bien être fait dans la super-classe.
  • C'est le cas dans cette solution, où l'appel à apply() est fait dans la méthode vieillir() de Humain, et les sous-classes Homme et Femme ont une méthode vieillir() qui commence par appeler la super méthode.

 

- prendre du poids avec les rencontres

  • Il existe plusieurs solutions pour la signature de la méthode de l'IF.
  • La solution la plus basique consiste à utiliser 2 paramètres de type Humain, sans contrainte.
  • Cela implique qu'il faut écrire une EL où il faut tester le type d'instance de ces paramètres, donc quelque chose du genre :
(h1, h2) -> {
    if ( h1.isHomme() || h1.isGarcon() ) {
        h1.grossir(loto.nextInt(21)); // faire grossir l'homme
        h2.grossir(10); // faire grossir la femme
    }
    else if ( h1.isFemme() || h1.isFille() ){
        h1.grossir(10); // faire grossir la femme
        h2.grossir(loto.nextInt(21) -10 ); // faire grossir l'homme
    }
}
  • Dans la solution proposée, une petite optimisation est utilisée : le premier paramètre doit être une instance d'Homme et le second de Femme et le troisième paramètre est un entier représentant le "sens" de la rencontre, c.a.d est-ce un homme qui rencontre une femme ou l'inverse.
  • Cela permet d'éviter de tester le type des instances dans l'EL. Il y a juste le sens de la rencontre à tester.
  • En revanche, cela suppose que l'on appelle la méthode de l'EL avec les bons paramètres. C'est pourquoi on trouve :
    • dans Homme : breeding.gainWeight(this, h, 1); car l'objet courant est bien un homme et h une femme
    • dans Femme : breeding.gainWeight (h, this, 0); car l'objet courant est une femme et h un homme.

 

- fertilité impactée par la taille de la population.

  • En fait, le cadre permettant d'ajouter cette fonctionnalité existe déjà : l'IF+EL pour faire grossir la population à la fin d'un tour de jeu.
  • Il suffit que la méthode de l'IF ne représente plus une simple prise de poids mais un traitement "générique" en fin de tour.
  • C'est pourquoi dans cette solution, la méthode a été renommée apply().
  • De plus, dans l'EL définie dans LifeGame, on ajoute les tests sur la taille de la population lorsque l'humain passé en paramètre est une femme.