les interfaces avec java, exemple correct?

a marqué ce sujet comme résolu.

Bonjour.

voilà, je suis dans la conception d’un projet de joueurs et on doit écrire des interfaces pour décrire le personnage en java, alors j’ai quelque petites questions à ce propos :

  • admettons j’ai une classe Personnage qui représente un joueur. Les joueurs vivent leur vie mais dans le jeu, certains sont des acheteurs compulsifs. Par definition, tout client du magasin A est un acheteur compulsif. Puis je alors ecrire une interface AcheteurCompulsif utilisée par la classe des clients du magasin A ? -Est ce logique? Je dis alors que les clients du magasin A se comportent comme des acheteurs compulsifs.

Example:

public class Personnage {
    // code personnage
}

public class ClientMagasinA extends Personnage implements AcheteurCompulsif {
    // code ClientMagasinA 
}

public interface AcheteurCompulsif {
    int acheter(Object o) {
        // code acheter
    }
}

Je mets ça car j’ai du mal à comprendre les interfaces, malgré les tutos. Est-ce un code logique??

Marius

public class ClientMagasinA extends Personnage implements AcheteurCompulsif

Le problème dans cette ligne est que tu défini que tous les Clients de ton Magasin A sont des acheteurs compulsifs or ce n’est pas forcément le cas.

Du coup je te propose quelque chose comme ça (ça fait ±1 an que je n’ai pas fait de Java mais je tente ;) )

public class Personnage { /*...*/ }

public interface Client extends Personnage
{
  void vaAcheter();
  default void acheter(Obj o)
  {
    /*tu achètes...*/
  }
}

public class AcheteurCompulsif implements Client
{
  void vaAcheter()
  {
    if(/*rand plus élevé que pour l'acheteur lambda*/)
      acheter(/*produit*/);
  }
}

public class AcheteurLambda implements Client
{
  //même principe avec un rand plus faible
  void vaAcheter()
  {
    if(/*rand plus faible que pour l'acheteur compulsif*/)
      acheter(/*produit*/);
  }
}

Comme ça tu as une interface commune pour les différents types de client et tu as juste à définir les méthodes communes dans chaque classe implémentant cette interface :D

Ca reste à adapter mais ça te fait une bonne base comme ça pour que tu comprennes le principe des interfaces :)

Merci Vanadiae pour cette réponse, je refait un essai pour être certain avec un autre exemple ici de bien comprendre les interfaces.

Il y a des personnages dans le jeu qui peuvent soit être des footballeurs, soit des triathloniens (j’ai pas trouvé meilleur exemple). Tous sont donc sportifs mais les triathloniens sont des nageurs, en plus…

public abstract class Personnage {
    // code personnage
}



// --- Classes non abstraites ---

public class Footballeur extends Personnage implements Sportif {
    public void s_entrainer() {
        // entrainement specifique au footballeur
    }
}

public class Triathlonien extends Personnage implements Sportif, Nageur {
    public void s_entrainer() {
        // entrainement specifique au triathlonien
    }

    public void nager() {
        // code pour nager
    }
}



// --- Interfaces ---

public interface Sportif {
    void s_entrainer();
}

public interface Nageur {
    void nager();
}

Le code est-il logique? ..ai je correctement utilisé le concept, d’interface ?

Marius

Au fait tu as mis

// —- Classes non abstraites —-
//
// interfaces

Or les interfaces sont des classes complètement abstraites. Quand tu déclares une classe abstract, tu peux très bien faire ça

public abstract class Foo {
  public abstract void fonction_abstraite();
  //ici tu as le droit d'en définir une pas abstraite
  public void fonction_non_abstraite() {}
}

public interface Bar {
  public abstract void abstraite();
  // tu peux pas faire ça
  //public void bar() {}

  //en revanche tu peux faire
  public default void bar() { /*code par défaut mais tu peux l'override après*/ }
}

C’est dans ces cas là qu’il faut faire la différence entre déclarer et définir:

//déclaration
void foo();
//définition
void foo { /*...*/ }

Au fait, tout à l’heure j’ai mis:

void vaAcheter()

Or il me semble qu’en java (contrairement au C++ que j’apprends), il faut mettre public, private ou protected avant chaque déclaration de fonction membre donc pense à le mettre

public class Foo {
  void vaAcheter() {}
  //devient
  public void vaAcheter() {}

Bonjour :)

Le problème dans cette ligne est que tu défini que tous les Clients de ton Magasin A sont des acheteurs compulsifs or ce n’est pas forcément le cas.

Du coup je te propose quelque chose comme ça (ça fait ±1 an que je n’ai pas fait de Java mais je tente ;) )

public class Personnage { /*...*/ }

public interface Client extends Personnage
{
  void vaAcheter();
  default void acheter(Obj o)
  {
    /*tu achètes...*/
  }
}

Vanadiae

Alors non, une interface ne peut pas étendre une classe.

L’intérêt de définir une interface est de pouvoir… utiliser cette interface :D , ou en d’autres mots, le contrat qu’elle définit. Donc si on reprend ton exemple de sportif, la logique voudrait plutôt qu’un nageur soit un sportif, et que la nage fasse partie de l’entraînement du triathlonien.

Sauf que ça oblige à dupliquer du code lorsqu’on va ajouter un décathlonien par exemple. Il vaut mieux donc implémenter tes comportements dans des classes et utiliser la composition afin de maximiser la réutilisation du code : voir le design pattern Strategy.

Or il me semble qu’en java (contrairement au C++ que j’apprends), il faut mettre public, private ou protected avant chaque déclaration de fonction membre donc pense à le mettre

public class Foo {
  void vaAcheter() {}
  //devient
  public void vaAcheter() {}

Vanadiae

Non, il y a une 4e visibilité par défaut (package-private). Elle pourrait être utilisée si la méthode en question ne faisait pas partie du contrat défini par l’interface Client. Pour respecter le contrat, la méthode doit obligatoirement être publique (sinon l’interface ne sert à rien puisqu’on ne peut pas appeler la méthode qu’elle déclare.

Merci chiniosfurax, je reprends l’exemple du sportif qui semble parlant…

Il vaut mieux donc implémenter tes comportements dans des classes et utiliser la composition afin de maximiser la réutilisation du code

j’essaye d’utiliser des interfaces pour m’y familiariser, que signifie la composition ? C’est l’héritage ? Que verrait-tu comme squelete de code?

j’essaye d’utiliser des interfaces pour m’y familiariser, que signifie la composition ? C’est l’héritage ? Que verrait-tu comme squelete de code?

marius007

Non, justement, composer c’est utiliser les propriétés de ton objet pour matérialiser leur relation et non l’héritage.

Pour le sportif :

public class Personnage {}

interface Sportif { void sEntrainer(); }

class Decathlonien extends Personnage implements Sportif {
    @Override
    public void sEntrainer() {
        System.out.println("Je cours");
        System.out.println("Je fais autre chose");
    }
}

class Triathlonien extends Personnage implements Sportif {
    @Override
    public void sEntrainer() {
        System.out.println("Je cours"); // code dupliqué éventuellement ici
        System.out.println("Je nage");
    }
}

De cette façon, ton code qui sait que ton personnage est sportif mais ne connait pas nécessairement sa discipline permet à ton personnage de faire son entrainement en appelant la méthode sEntrainer. Tu caches donc l’implémentation derrière l’interface là où cette première n’a pas besoin d’être visible.

Pour éviter de dupliquer le code du coureur, tu peux l’implémenter dans une classe dédiée à ce comportement, puis l’utiliser dans tes 2 implémentations de sportif. Par exemple :

class Coureur implements Sportif {
    @Override
    public void sEntrainer() {
        System.out.println("Je cours");
    }
}

class Triathlonien extends Personnage implements Sportif {
    
    private final Sportif coureur = new Coureur();

    @Override
    public void sEntrainer() {
        coureur.sEntrainer(); // le code n'est plus dupliqué
        System.out.println("Je nage");
    }
}

Bien sûr, tout dépend de ce que tu as besoin de faire, l’exemple ici suppose que tes comportements sont indépendants, ce qui n’est pas tout le temps le cas.

bonjour je remets le sujet car j’aimerais savoir si ce diagramme utilise bien les interfaces.

J’utilise une interface pour différencier les produits naturels qui peuvent aller dans la boite1 des produits nons-naturels qui vont dans la boite2 :

test
test
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte