Jeux Libres

Plateforme de création de jeux vidéo (Le site est en cours de création / réorganisation)


» Les Tutoriaux » L'héritage,les classes abstraites et interfaces

L'héritage,les classes abstraites et interfaces


Alors ici nous allons voir que des classes qui servent à créer des objets plus particulier peuvent, en Java hériter d'une et une seule classe créant un objet plus général.




L'héritage.


Notion d'héritage



L'héritage c'est en fait, une sorte de classement qui vise à placer tout au dessus, les classes se rapportant à des objets plus généraux (objet de ce monde par exemple) et au fur et à mesure en dessous, des classes d'objets plus particulier (moyen de transport, ...) afin de former au fur et à mesure, une hiérarchie.

La relation d'héritage se traduit par un bus est un moyen de transport.
Ne pas confondre avec les autres relations (agrégation, composition et dépendance ou cela se traduit plutôt par : une maison a un toit, etc...)



Exemple de hiérarchie :



La classe dont les autres classes héritent est appelée la super classe. (la classe mère = la superclasse)

Les classes héritées de la super classe sont appelées les sous classes. (classes filles = sous classes)

Tout ce que une super classe peut faire, ses sous classes peuvent aussi le faire!

Exemples d'héritage

Supposons que l'on aie une classe Point, et ensuite on veut créer une classe Circle qui aura en plus d'avoir un point, la longueur du rayon.

Notre classe Point : Bah là y'a pas vraiment grand chose qui change par rapport à avant :
Code : Java

public class Point
{
    // instance variables - replace the example below with your own
    private int x, y;

    /**
     * Constructor for objects of class Point
     */

    public Point()
    {
        y = 0;
        x = 0;
    }
    public Point (int x, int y) {
        this.x = x;
        this.y = y;
    }

    /**
     * An example of a method - replace this comment with your own
     *
     * @param  y   a sample parameter for a method
     * @return     the sum of x and y
     */

    public void move (int nvX, int nvY) {
        x = nvX;
        y = nvY;
    }
    public int getX () {
        return x;
    }
    public int getY () {
        return y;
    }
    public String toString () {
         return "Le point se trouve en ("+x+";"+y+")";
    }
}
 

Jusque là pas de nouveauté.
Bon maintenant je veux créer une classe Circle.
Je vais la faire héritée de la classe Point et pour celà en java, on utilise le mot clé "extends" que l'on met après le nom de la classe comme ceci :
Code : Java

public class Circle extends Point {}
 


Je vous montre maintenant la classe Circle donc :
Code : Java

/**
 * Write a description of class Circle here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Circle extends Point
{
    // instance variables - replace the example below with your own
    private Point centre;
    private int rayon;
    /**
     * Constructor for objects of class Circle
     */

    public Circle()
    {
        centre = new Point (0, 0);
        rayon = 0;
    }
    public Circle(int rayon)
    {
        centre = null;
        this.rayon = rayon;
    }

    /**
     * An example of a method - replace this comment with your own
     *
     * @param  y   a sample parameter for a method
     * @return     the sum of x and y
     */

    public void changeRayon (int nvR)
       
    {
        rayon = nvR;
    }
    public void move (int nvX, int nvY) {
        centre.move (nvX, nvY);
    }
    public int getRayon () {
        return rayon;
    }
    public String toString ()  {
        return "La longeur du rayon du cercle est : "+rayon+"\n"
        +"Le centre se trouve en : "+centre.getX()+";"+centre.getY()+")";
    }       
}
 


Vous voyez que la classe Circle peut logiquement aussi faire bouger le Point, et la classe Circle contient donc aussi les attributs de la classe Point, et un en plus même : la longeur du rayon!

Voilà je crois que j'ai fini mon tour sur la première partie du chapitre, je vais passer au point suivant : l'héritage des constructeurs.


L'héritage des constructeurs


Alors, si vous reprenez ma classe Circle, j'ai écrit ceci :
Code : Java

public Circle()
    {
        centre = new Point (0, 0);
        rayon = 0;
    }
 

Je lui dit donc de créer un point (le centre) qui a pour coordonnée : (0,0)
Ce n'est pas que cette solution n'est pas bonne, mais il y a moyen de faire encore plus simple!

L'utilité du mot clef super.



Ce mot clé permet en fait, de pouvoir créer automatiquement un objet de la classe Point, dans le constructeur de votre classe Circle :

Démonstration :


Bah vous pouvez remplacer la première instruction du constructeur de votre classe Circle par ceci :
Code : Java

super (0, 0);
 


Que fait le mot clé super ?

Ce mot clé en fait invoque automatiquement le constructeur de votre superclasse Point. (celui à 2 arguments)

Il faut qu'un constructeur identique soit définit dans votre superclasse.

Si vous écriver "super ();", c'est le constructeur sans arguments de votre classe Point qui est appelé et s'il y en a pas, un constructeur par défaut est appelé (celui qui met tout vos valeurs à null ou à zéro) dont je vous ai parler dans le chapitre consacré aux constructeurs!
Maintenant, on a donc plus besoin de déclarer une variable de type Point dans votre classe Circle, car le mot clef super le fait pour vous!

Vous pouvez l'enlever, mais si vous recompiler, il y aura un soucis avec vos méthodes, se sera l'objet du point suivant!

L'instruction contenant le mot clé "super" doit être la première ligne de votre constructeur!


La redéfinition des méthodes


Reprenons maintenant nos méthodes de notre classe Circle :
Je vais commencer par la méthode move qui donne ceci :
Code : Java

centre.move (nvX, nvY);
 

Le problème c'est que ont a plus maintenant notre variable centre, car dans le constructeur je l'ai remplacé par : "super (0, 0);"

Bah là aussi il suffira remplacer notre centre par le mot clefs super ce qui donne :
Code : Java

super.move (nvX, nvY);
 


Oui, mais, cela ne change rien par rapport à ce qu'on avait avant!

Patience, ça va venir, reprenons maintenant la méthode toString () qui renvoye donc les informations sur le cercle.

Utilité de l'héritage



Si vous vous rappeler, avant j'ai écrit ceci :
Code : Java


return "La longeur du rayon du cercle est : "+rayon+"\n"
        +"Le centre se trouve en : "+centre.getX()+";"+centre.getY()+")";
 

Franchement moi je trouves, je sais pas vous, mais c'est lourd car il faut ré écrire le code pour afficher les coordonnées du point qui représente le centre de notre cercle.
Alors que on a une méthode dans notre classe Point qui s'appelle toString et qui renvoie les coordonnées d'un Point.

Bah on peux bien sur remplacer notre centre.getX () et tout le blablabla par ceci :
Code : Java

public String toString ()  {
        return "La longeur du rayon du cercle est : "+rayon+"\n"
        +"Le centre : "+super.toString();
    }
 


Vous voyez donc que l'héritage nous permet donc d'éviter de devoir réécrire du code inutilement!!!

Un dernier petit mot sur les variables



On pourrait très bien vouloir rendre accessible les variables de notre superclasse Point dans notre sous classe Circle et écrire aussi ceci :

Code : Java

return "La longeur du rayon du cercle est : "+rayon+"\n"
        +"Le centre se trouve en : "+centre.x+";"+centre.y+")";
 

Pour cela il faut remplacer le mot clef private qui se trouve dans votre classe Point (à la déclaration de vos variables) par le mot clef "protected" comme ceci :
Code : Java

protected int x, y;
 


Remarque avec la méthode toString ()


Si vous n'avez pas définie de méthode toString dans vos classe, et sur un objet de cette classe, il va vous afficher l'adresse mémoire de votre objet, car, la méthode toString() est présente dans une superClasse nommée Object dont je vous parlerai dans le tutoriel suivant.

Donc comme le compilateur ne trouvera pas de méthode toString() dans votre classe Circle, ni dans votre classe Point, il va utiliser celle de la classe Objetct dont hérite toute les classe et elle affiche l'adresse mémoire des objets.
D'ailleurs mettez les méthode toString en commentaire, et essayer de l'appeler sur un objet de type Circle, normalement il vous met l'adresse en mémoire de votre objet!

Remarque :
Code : Java

Circle c1 = new Circle ();
System.out.println (c1.toString ());
System.out.println (c1);
 

Ecrire juste le nom de l'objet revient au même que d'appeler la méthode toString () sur lui même.

Le mot clef protected



Il signifie que seul les classes qui sont dans le même package auront accès aux variables de celle-ci, et/ou aux méthodes.

Cette solution est déconseillée car elle ne respecte pas le principe de l'encapsulation dont je vous ai parler dans un des chapitres précédant, chaque classe est responsable de ses variables, et seul ses méthodes pourront modifier la valeur de ses variables!

Ce mot clef n'est donc pas utile sauf si vous posséder des méthodes qui devront être utilisable que dans le package ou se trouve votre classe.


La redéfinition des méthodes et le polymorphisme


Une chose bien pratique : redéfinir les méthodes!



La redéfinition d'une méthode n'est rien d'autre qu'une méthode présente dans une classe mère, dont son en tête a été reprit tel quel dans les classes filles, mais, par contre le corps de la méthode à changé.

Donc seul le corps de la méthode change, on dit qu'elle a été redéfinie!

Ne pas confondre la redéfinition de méthodes et la surcharge des méthodes :
La surcharge des méthodes : toutes les méthodes sont dans la même classe et ont une signature différente. (même nom mais la liste des types de leurs arguments varie)

La redéfinition de méthode : toutes les méthodes ont la même signature, mais sont dans des classes différentes qui sont héritées. Seul le corps de la méthode change, car la méthode applique un comportement différent en fonction du type de l'objet bien précis! (plus général ou plus spécifique)
L'en tête d'une méthode redéfinie dans une sous classe est pareil à celui de la méthode présente dans votre superClasse! (même type de retour, même nom et même liste des types de ses arguments, etc...)

La superclasse de toutes les classes!



Et oui, je ne vous l'ai pas dis, mais sachez que toutes vos classes qu'elles soit créées ou préexistantes héritent automatiquement de la classe Object!!

Celle-ci comporte déjà quelques méthodes :

Les méthodes de la classe Object



Une intéressante est la fameuse méthode equals, en effet, comme les pointeurs n'existent pas en Java, lorsqu'on compare deux objets entre eux à l'aide du ==, on compare des références donc si vous écrivez :
Code : Java

if(chaine1 == chaine2)
 


L'expression renvoyera faux même si vos deux chaînes de caractères sont identiques, car là vous comparer des références et ces 2 chaînes évidement ont pas la même adresse en mémoire!!

Comment peut-on comparer deux objets entre eux alors ?

Bah c'est là qu'intervient notre méthode equals.
Cette méthode ne se base pas sur les références des objets, mais sur des caractéristiques bien précises tel que par exemple, si les deux chaînes ont les mêmes caractères, la méthode equals renvoye vraie.

La surcharge des opérateurs comme en c++ n'existe pas en Java, pas la peine d'essayer d'écrire :
Code : Java

public operator== (String chaine2) {}
 

Comment faire pour comparer des autres objets que des String alors ?

Bah c'est là que va intervenir la redéfinition des méthodes, comme toutes les classes héritent de la classe Object, Toutes vos classes pourront redéfinir la méthode equals en fonction de vos critères, fin un exemple vaudra mieux qu'un discours.

Exemple de redéfinition de méthodes!

Bah je vais là redéfinir la méthode equals dans ma classe Point, deux point seront identiques lorsqu'ils auront les même coordonnées (évidement j'aurais pu rajouter un nom de type char à mes points, mais je vais pas le faire se sera plus simple)

Alors ça donne ceci ma méthode equals redéfinie dans la classe Point :
Code : Java

public boolean equals (Point p2) {
        if (x == p2.x && y == p2.y)
            return true;
        else
            return false;
    }
 

On peut même faire encore plus simple!
Code : Java

public boolean equals (Point p2) {
       return x == p2.x && y == p2.y;
}
 

Et maintenant je vous propose de redéfinir la méthode equals dans votre classe Circle mais là évidement il faudra faire une méthode qui renvoye le centre du Cercle.
Donc bah je suis obligé d'écrire ceci avant, on va dire que l'on va clôner notre Point qui représente le centre du Cercle.
Code : Java

public Point getCentre () {
      return new point (super.getX(), super.getY());
}
 


On aurait très bien pu faire une méthode clone dans notre classe Point!

Maintenant plus qu'à faire notre méthode equals qui donne ceci :
Code : Java

public boolean equals (Circle c2) {
    public boolean equals (Circle c2) {
           return (super.equals (c2.getCentre())) && (rayon == c2.rayon);
    }
 


Je vous force à faire pour chacune de vos classe une méthode equals, une méthode toString et une méthode clone, vous voyez ici j'en ai eu besoin!
Maintenant on peux tester, essayer de créér deux objets de type Point, mettez leur les mêmes coordonnées puis appliquer la méthode equals sur l'un des deux, vous verrez ce que vous renvoie la méthode equals. (désolé pas de screen shot pour le moment, David à pas encore mit un hébergeur d'images apparemment)
Normalement vous devriez voir une fenêtre et au milieu noté boolean true surligné en jaune.

Le polymorphisme



C'est une conséquence due à l'héritage, les objets instance de vos sous classes sont aussi instance de votre superclasse puisque l'héritage me dis : un Cercle est un Point!

Donc si vous invoquer une méthode de la classe Point sur un objet de type Circle, cela ne pose pas de problème, le compilateur va rechercher votre méthode de votre superclasse s'il ne la trouve pas dans votre sous classe!
Le polymorphisme :
Un objet expéditeur d'un message n'a pas besoin de connaître le type précis de l'objet destinataire pour réaliser un envoi de message, c'est le compilateur lui même qui se chargera de naviguer dans la hiérarchie de vos classes afin de trouver la bonne méthode.
Et donc on peut faire appel à une méthode sur des objets de type différents! Le compilateur saura savoir dans quel classe la méthode se trouves!
C'est ça qui fait vraiment la puissance de la POO!

Le contraire n'est pas autorisé et c'est logique, on ne vas pas changer le rayon d'un Point!

Donc retenez : une sous classe sait faire tout ce que votre superclasse sait faire, mais votre superclasse ne sait pas faire tout ce que votre sous classe peut faire.


La covariance des variables



Le casting implicite et le casting explicite



Le casting implicite :
Il s'agit de de faire passer un objet de votre classe fille pour un objet de votre classe mère!
Exemple :
Code : Java

Point p1 = new Point ();
Circle c1 = new Circle ();
p1 = c1;
 

Le compilateur là ne bronchera pas, car un cercle est un point, par contre si vous écrivez ceci :
Code : Java

c1 = p1;
 

Bah vous dîtes de mettre un objet de type Point (plus général) dans un objet de type Circle, (qui est plus particulier) là votre compilateur va pas accepter!!
Le casting explicite
Bah là il faudra préciser au compilateur que vous savez ce que vous faîtes, on utilisera tout bêtement l'opération de cast comme ceci :
Code : Java

c1 = (Circle) p1;
 

Cela s'appelle le transtypage.

Voilà j'ai fait le tour de ce qui concerne l'héritage même, nous pouvons attaquez le point suivant : les classes abstraite!

Ha oui, une dernière chose :
L'héritage multiple n'est pas géré par le Java, une sous classe ne peut hérité que d'une seule superclasse!
Donc ne sera héritée que de la classe Objet (ça d'office de toute façon) et d'une et une seule autre classe!
Interdit d'écrire :
Code : Java

public class Voiture extends MoyenDeTransport, ObjetRoulant
{}
 



Les classes abstraites


Leur utilité



Elles servent lorsque des superclasses ne peuvent pas instancier d'objets.
Une classe abstraite ne peut donc pas créer d'objets!!

Une classe doit être déclarée abstraite lorsque au moins une de ses méthodes est abstraite.

Les méthodes abstraites



Bah c'est des méthodes qui n'ont pas de corps, ce sont des méthodes qui ont donc juste une en tête!

Le contrat fixé par les classes abstraite lors de l'héritage!



Toutes les méthodes abstraites contenues dans la superclasse devront être redéfnie dans leurs sous classes et si la sous classe contient encore des méthodes abstraites, elle sera abstraite également et ne pourra pas être instanciée!

On veut un exemple!
Bon d'accord, bah bonne appétit alors :

Nous allons ouvrir un nouveau projet blue J :
Project => open Project => people.
Ouvrez la class Person : Vous voyez qu'elle est déclarée abstraite car il y a le mot clef abstract devant!

La je ne vois pas de méthodes abstraites, mais essayer de créer une personne, vous aller voir que vous ne pouvez pas!

Ouvrez maintenant la classe Student par exemple.
La elle hérite de personne, si vous remarquer bien il y a le mot clefs super que l'on a vu qui permet de créer une personne qui sera ensuite Etudiant ou autre. Mais vous ne pouvez pas utilisez de new pour créer une personne car la classe Personne est abstraite!

Si vous regarder la classe Staff c'est pareil.
Ne vous occupez pas trop de la classe Database pour le moment, je vous en reparlerai quand je vous parlerai des listes!

Bon bah maintenant nous allons reprendre notre fameuse classe Point en supposant qu'on ne veut pas l'instanciée.

Je veux que ma méthode move soit abstraite aussi, et donc qu'on ne sache plus bouger le centre, sans bouger le cercle!

Bon, là je modifie donc ma mèthode move en mettant après le mot clef public, le mot clef abstract comme ceci :
Code : Java

public abstract void move (int nvX, int nvY);
 

Je suis obligé de déclarer ma classe Point abstraite comme ceci :
Code : Java

public abstact class Point {}
 

Voilà, maintenant je suis obligé de redéfinir la méthode move dans la classe Circle. (bah je vois que là c'est déjà fait!)

Mais ça plante parce que la méthode n'a pas de corps dans votre super classe pour s'exécuter! On va donc devoir le préciser dans la sous classe!
Je vais pour cela rajouter des setters dans la classe Point comme ceci :
Code : Java

public void setX (int x) {
        this.x = x;
    }
    public void setY (int y) {
        this.y = y;
    }
 

Et il reste plus qu'à redéfinir la méthode dans la classe Circle comme ceci :
Code : Java

public void move (int nvX, int nvY) {
        super.setX (nvX);
        super.setY (nvY);
    }
 

Il y aura un autre problème à la méthode getCentre; car elle instancie un nouveau Point hors pas de new avec les classes abstraites, il faudra donc là créer une méthode qui renvoiera le Point lui même, on va donc utiliser notre mot clef this ce qui donne donne :
Code : Java

public Point getPoint () {
        return this;
    }
 

il reste à refaire la méthode getCentre dans la classe Circle :
Code : Java

public Point getCentre () {
        return super.getPoint ();
}
 

Là normalement ça doit compiler sans problème.
Voilà maintenant vous ne pouvez plus que créer des Cercles!

Vous voyez donc c'est génial hein ?!

Bon je l'avoue, faudrait surcharger le constructeur de la classe Circle pour pouvoir mettre des autres Coordonnée que 0,0 pour le centre, mais ça je vous laisse faire!


Les interfaces


C'est du 100% abstrait!



Comme l'héritage multiple n'est pas géré par le Java, il a fallut trouver une alternative au cas ou cela serait nécessaire.

Utilité des interfaces


Celle-ci servent surtout à créer des nouvelles superclasses qui pourront être implémentées dans des autres classes, mais ses classes (interfaces) sont 100% abstraites!

Ca veut dire que les interfaces ne contiendront que des méthodes abstraites, donc une interface n'est rien d'autre qu'une classe contenant uniquement des en-têtes de méthodes.

Exemple d'interfaces

Il y en a déjà qui sont connues comme par exemple les interfaces ActionListener, MouseListener, etc...
Elles contiennent toutes les méthodes qui doivent être redéfinies lorsqu'on effectue un clic de souris, etc ...

Mais je ne vais pas expliquer la POO évènementionelle maintenant, on va donc reprendre notre classe Circle!

Supposons que l'on veuille maintenant faire une méthode qui fera tourner le cercle.

-On pourrait la faire dans la classe Point, mais là les Point tournerons aussi et je ne veux pas y toucher, le centre doit rester immobile, le Cercle dois donc tourner sur lui même!

-Bah pas de problème, il suffit de rajouter la méthode dans la classe Circle.
On pourrait le faire, mais il y a des contraintes là :

-Vous devrez mettre en œuvre une convention de nommage entre vous et le programmeur utilisant vos objets, vous ne devrez pas utilisez une méthode tourner si un autre programmeur utilise rotation par exemple.

-Adieu le polymorphisme, vous ne pourrez pas appeler la méthode tourner sur des autres objet que ceux de la classe Circle!

Donc il faudrait pouvoir créer une superclasse mais le problème c'est que comme l'héritage multiple est interdit en Java, vous ne pourrez donc pas faire héritée la classe Circle de votre classe qui fera tourner votre cercle car Circle hérite déjà de Point!

C'est là qu'on va utilisez les interfaces!

Création d'une interface


Vous cliquer sur new class, cocher la case Interface et donner lui un nom. (moi je l'ai appelée InterAction)

Effacez ce qui est écrit entre les crochets délimitant l'interface et écrivez l'en tête de la méthode tourner.

Vous pouvez aussi donner l'en tête de la méthode rotation, ainsi le programmeur utilisant vos objets pourra utiliser celle qu'il désire.

Voici le code de mon interface, franchement le code des interfaces, c'est vraiment le plus simple de toutes les classes!

Code : Java

public interface InterAction
{   
   public void tourner ();   
}
 

C'est super simple, il n'y a que des en tête de méthodes!

Bon maintenant il faut implémenter notre interface dans la classe Circle, ceci se fait comme ça :

Implémentaton des interfaces.


Code : Java

public class Circle extends Point implements InterAction
 

Votre classe peut aussi implémenter plusieurs interfaces à la fois comme ceci :
Code : Java

public class Circle extends Point implements interface1, interface2
 


Vos interfaces peuvent aussi implémenter des sous interfaces!
Code : Java

public interface InterAction implements sousInterface1
 

Et les interfaces peuvent hériter d'une autre interface uniquement (cas plus particulier) mais pas d'une autre classe!
Code : Java

public interface InterAction extends interfaceMere
 

Attention l'ordre des mots est important! Vous ne pouvez par écrire ceci :

Code : Java

public class Circle implements InterAction extends Point
 



Donc l'ordre des mots est toujours comme ceci :
extends classeMere implements interfaces

Bon maintenant il ne reste plus qu'à redéfinir notre méthode tourner dans notre classe Circle!
Code : Java

public void tourner () {
     System.out.println("Je tourne!");
}
 

Le contrat fixé entre les classes implémentant une interface :


Toutes les classes implémentant une interface devront obligatoirement redéfinir toutes les méthodes contenue dans cette interface!

On pourra ainsi redéfinir cette méthode dans toutes les classes implémentant cette interface! Cela permet le polymorphisme, la méthode tourner pourra être appelée via n'importe quel objet implémentant cette interface!

Donc vous pouvez refaire une classe Segment et redéfinir votre méthode tourner en implémentant l'interface InterAction dans votre classe Segment.
Essayez ça ne fait pas de mal!

Et pour vous donnez un dernière aperçu, on pourra utiliser notre interface InterAction comme on utilise une superclasse, on pourra donc utiliser le polymorphisme!

Voici un exemple avec un main, je suppose que j'ai deux classes Circle et Triangle :
Code : Java

public class Test {
       public static void main (String[] args) {
              InterAction i1 = new Circle (); //Covariance des variable!
              Interaction i2 = new Triangle ();
              i1.tourne ();
              i2.tourne ();
       }
}
 

Les interfaces nous permettent donc d'utiliser à nouveau le polymorphisme dans toute sa splendeur!

Sachez que l'on peut aussi définir des constantes dans une interfaces! Mais celles-ci seront d'office public static final!

Exemple de déclaration d'une constante dans une interface :
Code : Java

public interface Modele {
       int MAX_VIES = 3;
       int MIN_VIES = 0;
       public void methode ();
}
 


Les mots public static et final sont facultatifs car dans les interfaces, on a d'office des constantes statique et publiques. Faites attention donc à ce que vous pouvez mettre dans vos interfaces.

On voit donc que les interfaces permettent donc de faire quasiment de l'héritage multiple.
Java à utiliser cette façon de faire car l'héritage multiple pose beaucoup de difficultés si il est mal géré!
Ainsi, les interfaces sont des genres de superClasse qui permettent de définir facilement ce que une classe sait faire à son utilisateur. Les interfaces contiennent donc des informations sur les classes!!
On utilise parfois des interfaces de définition avec juste un nom : exemple : seule les classes implémentant tel interfaces pourront faire tels chose!!


Exercices sur l'héritage


1)L'héritage : bon voilà alors je vais vous faire un exercice comme si on allait créer un mmorpg.

Alors je vais vous demander de faire une classe Personnage, qui devra être capable de :
Créer des personnages et ils divent avoir un pseudo, le niveau doit être initialisé à 1, leur niveau de compétences aussi, et leur vie à 100, et leur point de mana à 100 aussi!
Cette classe devra pouvoir ajouter de la vie à un de vos personnage
boirePotionDeVie (int quantite)
une méthode recevoir dégats qui enlèvera des point de vie à votre personnage.
Une méthode attaquer qui permettra d'attaquer un autre personnage.
Et une méthode qui renvoie vrai si le personnage est vivant
Et une méthode afficher pour afficher l'état actuel de tout vos personnages du mmorpg.
[attetion]Attention, pas de point de vie négatif![/attention]

Ensuite je vais vous demander de faire une classe arme, qui créera des armes. (nom et l'attaque (le nombre de dégat qu'elle cause)
Et une méthode changer pour qu'un personnage puisse changer d'arme!

Ensuite je vous demanderai de faire une sous classe Magicien qui héritera de Personnage qui pourra en plus, lancer des soritlèges. Par contre il pourra équipé qu'un baton qui fera moins de dégat qu'une épée. (logique)

Et faîtes aussi une classe guerrier qui aura une méthode tapper à l'épée, une autre qui renveoiera vrai ou faux s'il est sur son cheval, enfin soit, rien ne vous empêche d'inventé de nouvelles fonctionnalité à vos classe, et oui, vous devrer avoir un esprit imaginatif!
2)Les classes abstraites.

Je veux que vous fassiez maintenant en sorte que l'on ne puisse plus instancier de personnages. (plus que des magiciens ou guerrier!)

Les armes équipées seront définie dans la classe contenant le main! (mais rien ne vous empêche de faire des sous classes de Arme qui crée des armes spécialisées)

Je veux aussi que vous créer une méthode abstraite dans la classe Personnage, il s'agit de la méthode attaquer et vous devrez la redéfinir dans vos sous classes magicien et guerrier!
Et pour les plus ardus, faîtes une classe Arme abstraite.

Il vous faudra faire une interface et l'implémenter dans ces deux classes (magicien et guerrier), et oui! Magicien et Guerrier hériteront déjà de Personnage et héritage multiples interdit en Java.


Je trouves que c'est vraiment un bonne exercice! (pour une fois j'ai vraiment trouvé quelquechose de bien je crois)
Faîtes aller votre imagination! Mais vous devez utiliser les notions d'héritage, classe abstraites et méthodes abstraites et interface.
Faîtes en jusqu'à que vous vous y sentez à l'aise car on va beaucoup les utiliser dans la partie III afin de ne pas réécrire du code qui existe déjà.


Solution des exercices.


Solution de l'exercice n° 1 :

Vous n'avez peut être pas fait la même chose que moi à 100%, mais je vais vous montrer ce que moi j'ai fait.

Alors je commence par ma classe Arme :
Code : Java


/**
 * Write a description of class Arme here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Arme
{
    private String nom;
    private int attaque;
    public Arme (String nom, int attaque) {
        this.nom = nom;
        this.attaque = attaque;
    }
    public void changer (String nvNom, int nvAttaque) {
        nom = nvNom;
        attaque = nvAttaque;
    }
    public int getNbDegats () {
        return attaque;
    }
    public String toString () {
        return "Nom de l'arme : "+nom+" attaque : "+attaque+"\n";
    }
}
 


Ensuite voici ma classe Persnnage :
Code : Java


/**
 * Write a description of class Personnage here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Personnage
{
    // instance variables - replace the example below with your own
    private int vie;
    private int mana;
    private String pseudo;
    private int niveau;
    private Arme arme;
   
    /**
     * Constructor for objects of class Personnage
     */

    public Personnage(String pseudo)
    {
        this.pseudo = pseudo;
        vie = 100;
        mana = 100;
        niveau = 1;
        arme = null;
    }
    public void upper () {
        niveau++;
    }
    public void attaquer (Personnage p) {
        int degats = arme.getNbDegats ();
        p.recevoirDegats (degats);
    }
    public void recevoirDegats (int degats) {       
        vie -= degats;
        if (vie < 0) vie = 0;
    }
    public boolean retirerMana (int quantite) {
        mana -= quantite;
        if  (mana < 0) {
            System.out.println("Pas assez de poitn de mana pour lancer le skill!");
            mana += quantite;
            return false;
        } else
            return true;
    }
    public void boirePotionDeVie (int quantite) {
        vie += quantite;
        if (vie > 100) vie = 100;       
    }
    public void boirePotionMana (int quantite) {
        mana += quantite;
        if(mana > 100) mana = 100;
    }
    public boolean estVivant () {
        return vie != 0;
    }
    public void changerArme (Arme nvArme) {
        arme = nvArme;
    }
    public Arme getArme () {
        return arme;
    }
    public int getVie () {
        return vie;
    }
    public int getMana () {
        return mana;
    }
    public String toString () {
        return "Vie : "+vie+" Mana = "+mana+" arme = \n"+arme.toString ();
    }
}
 


Alors la classe magicien :
Code : Java


/**
 * Write a description of class Magicien here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Magicien extends Personnage
{ 
    boolean assezDeMana;
    private Arme arme;
    // instance variables - replace the example below with your own
   public Magicien (String pseudo) {
       super(pseudo);       
   }
   public void lancerUnSors (String nom, int degats, int nbMana, Personnage cible) {
        assezDeMana = super.retirerMana (nbMana);
        if (assezDeMana) {
            cible.recevoirDegats (degats);
        }       
   }   
}
 

et enfin la classe Guerrier
Code : Java


/**
 * Write a description of class Guerrier here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Guerrier extends Personnage
{
private boolean estSurSonCheval;
    public Guerrier (String pseudo) {
       super(pseudo);
       estSurSonCheval = false;
    }
    public void monterSurLeCheval () {
        estSurSonCheval = true;
    }
    public void descendreDuCheval () {
        estSurSonCheval = false;
    }
}
 

Et pour ceux qui veulent, voici ma casse pour tester.
Code : Java


/**
 * Write a description of class Test here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */

public class Test
{
    // instance variables - replace the example below with your own
    public static void main (String[] args) {
        Magicien m = new Magicien ("white lord");
        Guerrier g = new Guerrier ("Fenhim");
        m.changerArme(new Arme ("Rod", 10));
        g.changerArme (new Arme("Escalibur", 40));
        g.attaquer (m);
        m.lancerUnSors ("jupiter thunder", 30, 20, g);
        g.boirePotionDeVie (10);
        System.out.println(m.toString ());
        System.out.println(g.toString ());
    }
}
 

Voilà tout bête le première exercice, là ou les choses vous se corser, c'est à l'exercice suivant, je vais pas mettre la solution rapidement d'ailleur.




Donc, grâce à l'héritage, on voit la puissance du polymorphisme qui permet d'appeler automatiquement la méthode dans la bonne classe sans se soucier du type de l'objet.
L'héritage évite aussi de devoir retaper du code contenu dans la classe mère, dans les classes filles. (la redéfinition des méthodes, constructeurs, ...)
L'héritage multiple n'existe pas en Java, mais une classe peut implémenter plusieurs interfaces.



Rédigé par Lo



Hébergeur du site : 1and1.fr



Site de création de Jeux Vidéo
Apprenez à créer vos propres Jeux Video

A propos de la construction du site...
352257 pages ont été consultées sur le site !
Dont 252 pages pendant les 24 dernières heures.

Page générée en 0.941 secondes


Nos partenaires
- Otium Production : Aide aux débutants à créer leurs jeux
- Construis ton jeu en PHP : Apprenez à créer votre jeu en PHP
- A.C.S.E.L. : Club de patinage artistique de Caen


  © 2005-2008 www.jeux-libres.com - Toute reproduction totale ou partielle du contenu de ce site est strictement interdite.