Problème classe et méthode abstract

dav79
Problème classe et méthode abstract

Bonjour, voilà je suis entrain d'étudier les classes abstract, mais je rencontre un probème, ou je suis un peu bloqué, j'ai regardé un peu sur les FAQ, mais je n'est pas trouvé la solution vraiment à mon problème, qui est le suivant :

J'ai trois classes : une classes abstract et deux classe qui hérite de la classe abstract
- abstract class FonctionNommee
- class CosMoinsNommee
- class ImprimerFonction

Voici la composition de ces classes en gros

Quote:

// Classe FonctionNommee
abstract class FonctionNommee
{
String nomFonction;

abstract double calculer(double x);
void imprimer() {.......Corps du code.....;}
}

// Classe CosMoinsNommee
class CosMoinsNommee
{
String nomFonction
//Constructeur
CosMoinsNomme(String nomFonction){............}

// Méthode redéfinit
double calculer(double x) {.......... Corps du code ...........}
}

class ImprimerFonction
{
ImprimerFonction();
double calculer(double x) {return 0;}
void lister();
}

Donc en fait, j'ai compilé la classes FonctionNomme et la CosMoinsNommee, pas de problème jusque là
Par contre lorsque que j'ai compilé la clase ImprimerFonction, le problème c'est posé.

D'après la documentation que j'ai consulté quand on utilise une classe abstract pour toutes les méthodes abstract de cette classe doivent être redédéfinit dans les sous-classes de la classes abstract.
Et donc cela signifie que dans cette exemple qu'il faut absolument que je redéfinisse la méthode calculer() à la fois dans la classe CosMoinsNomme et dans la classe ImprimerFonction.

C'est là le problème, je souhaiterai redéfinir cette méthode uniquement dans la classe CosMoinsNomme car c'est uniquement dans cette classe que je rédéfinit calculer.

Si je déclare uniquement la fonction calculer dans la classe ImprimerFonction en abstract, il me met se message :

Quote:

Math/ImprimerFonction.java:4: Math.ImprimerFonction is not abstract and does not
override abstract method calculer(double) in Math.ImprimerFonction
class ImprimerFonction extends FonctionNommee
^
1 error

Cela signifie que ma classe ImprimerFonction n'est pas abstract, donc aucune méthode de cette classe ne peut être mis en abstract.

si je met le corps met rien à l'intérieur du corps de cette fonction, il me dit que j'ai oublié le return car la signature de la méthode calculer est la suivante :

Quote:

double calculer(double x)

Donc ce que j'ai fait pour contourner le problème j'ai mis return 0 dans le corps de la fonction, est ce qu'il aurait un autre moyen pour résoudre ce problème, je souhaiterai que le compilateur ne prenne en compte la rédéfinition de la méthode calculer dans la classe ImprimerFonction, avec des anotations par exemple, je pense que ça doit être possible, je pensais que ça allait marché avec @override, mais j'ai pas bien compris le principe peut être aussi que ça dépend des version JDK, Moi j'ai la version 6.0....

j'espère que j'ai été claire dans l'explication, n'hésiter pas à me demander des précisions.

Désolé pour la longueur du message.

Merci pour votre aide

dav79

fredericmazue

Quote:
j'espère que j'ai été claire dans l'explication

Non... ;)
Mais on va essayer de t'aider quand même :)

Quote:
D'après la documentation que j'ai consulté quand on utilise une classe abstract pour toutes les méthodes abstract de cette classe doivent être redédéfinit dans les sous-classes de la classes abstract.

Oui.
Quote:
Et donc cela signifie que dans cette exemple qu'il faut absolument que je redéfinisse la méthode calculer() à la fois dans la classe CosMoinsNomme et dans la classe ImprimerFonction.

Non
Ou du moins pas forcément. Si tu as
class ImprimerFonction extends FonctionNommee
C'est oui
Mais si tu as
class ImprimerFonction extends CosMoinsNommee
C'est non car dans ce cas ImprimerFonction hérite de l'implémentation de calculer dans CosMoinsNommeee Et tel que tu poses ton problème c'est cee que tu veux.
Donc pour résoudre pas besoin d'annotions ou autres trucs fumeux. Simplement tu dérives de CoisMoinsNomme au lieu FonctionNommee

Maintenant si tu me le permets, le simple fait de dériver pour écrire ImprimerFonction me semble une faute de programmation. Enfin pas une faute stricto sensu, mais un viol des bons principes des Design Pattern. Bon si c'est ce qu'on t'a demandé de faire, on va pas discuter.
Sinon ImprimerFonction ne devrait pas dériver de quoi que ce soit, mais être une classe qui implémente une fonctionnalité d'impression, et alors CosMoinsNommee doit avoir comme membre une instance de ImprimerFonction et la méthode imprimer de CosMoinsNommee invoquera alors les méthodes de ImprimerFonction.
Gros avantage, ImprimerFonction va servir tout le temps, c'est ce que appelle un découplage. Sinon, le jour où tu écris une classe CosPlusNommee tu vas devoir encore dériver pour pourvoir l'imprimer.

J'espère que j'ai été cair dans l'explication. N'hésite pas à me demander des précisions ;) :)

mourad.zamoun Portrait de mourad.zamoun

si tu veux ne pas redefinir ta methode calculer, tu met la class ImprimerFonction comme abstract.

A+
Mourad :)

fredericmazue

Quote:
si tu veux ne pas redefinir ta methode calculer, tu met la class ImprimerFonction comme abstract.

Pourquoi pas. Mais j'avoue que dans le contexte du problème, je ne saisi pas bien l'intérêt pratique. Si la classe ImprimerFonction est abstraite, on ne peut pas imprimer avec...
Est-ce que j'ai loupé un épisode ?
mourad.zamoun Portrait de mourad.zamoun

a moins que le model n'est pas encore au point ?

fredericmazue

Quote:
a moins que le model n'est pas encore au point ?

Ca c'est sûr :)
D'ailleurs à l'attention de dav79:
dav79 wrote:
double calculer(double x)
Donc ce que j'ai fait pour contourner le problème j'ai mis return 0 dans le corps de la fonction

De même qu'il ne devrait jamais y avoir de code dupliqué dans un programme, il ne devrait jamais avoir de "fausses implémentations" comme celle du return 0
En fait, comme le dit m.zamoun, le modèle n'est pas au point. Il ne devrait pas y avoir de méthode "calculer" dans la classe ImprimerFonction, mais seulement dans CosMoinsNommee. Ce qui est dire autrement la même chose que ce que j'ai voulu dire avec mon histoire d'instance de ImprimerFonction membre de CosMoinsNommee. Mais j'avais oublié de bien lpréciser que dans ce cas la classe ImprimerFonction n'a pas (et ne doit pas avoir) de méthode "calculer". Ou, pour te résumer ça en une phrase, ImprimerFonction ne devrait dériver ni de FonctionNommee ni de CosMoinsNomme. Il n'y a aucune raison de dériver là.
dav79

Je pense que j'était claire dans mon explication,

Le problème n'est pas de savoir si l'implémentation est judicieuse ou non, c'est juste des tests, je suis les ennoncées de l'exercice, c'est pas moi qu'a fait l'analyse

Je rappel rapidement mon souci. J'ai trois classes :

- 1 class abstract FonctionNommee qui deux méthodes :
-- abstract calculer()
-- void imprimer(double x) {...................}

- 1 class CosMoinsNommee() : sous-class de FonctionNommee
-- le constructeur
-- méthode redéfinit calculer(double x) {...................}

- 1 class ImprimerFonction sous-classe FonctionNommee a deux méthodes
--- Constructeur
--- void lister(){................}
-- calculer // Car je suis obligé de redéfinir cette méhode,

La classes ImprimerFonction ne peut être déclaré en abstract car la méthode lister() n'est pas une méthode abstract, c'est bien là le problème.

Au départ je n'avais pas mis la méthode calculer dans la classe ImprimerFonction, mais le compilateur ne l'accepte pas, puisque que la classe ImprimerFonction est une sous-classe de la classe FonctionNommee, on doit obligatoirement redéfinir les méthodes abstract dans les classes filles. Et donc ici je doit redéfinir calculer() dans les sous-classes CosMoinsNomme et ImprimerFonction.

Moi je souhaiterai redéfinir calculer dans CosMoinsNomme, comment faire pour faire comprendre au compilateur qu'il n'est pas nécessaire de rédifinir calculer dans la class ImprimerFonction, tout tenant compte que la classe ImprimerFonction doit être une sous-classe de class FonctionNommee.

Est ce que maintenant c'est plus claire.
C'est pourquoi j'ai parlé d'annotation comme par exemple @override, je crois que cette instruction veut dire que le compilateur ne tient pas compte de la redéfinition de la méthode de la classe parent.

Est ce que vous avez cerné mon problème maintenant, est ce quelqu'un aurait une solution, naturellement je pense que oui, ça doit être un problème classic de débutant que j'expose, j'attends vous réactions.

Je vous remercie par avance,

dav79

fredericmazue

Quote:
Je pense que j'était claire dans mon explication

C'était clair et on avait compris.
Par contre toi si tu voulais prendre le temps de comprendre les réponses....

Quote:
Le problème n'est pas de savoir si l'implémentation est judicieuse ou non, c'est juste des tests, je suis les ennoncées de l'exercice, c'est pas moi qu'a fait l'analyse

Oui oui on avait deviné que c'était un exercice. Si tu lis ma première réponse j'y fais allusion.

Quote:
- 1 class ImprimerFonction sous-classe FonctionNommee a deux méthodes
--- Constructeur
--- void lister(){................}
-- calculer // Car je suis obligé de redéfinir cette méhode,

Donc NON, comme je te l'ai dit dans ma première réponse, tu n'es pas obligé de redéfinir cette méthode

Quote:

Est ce que vous avez cerné mon problème maintenant, est ce quelqu'un aurait une solution, naturellement je pense que oui, ça doit être un problème classic de débutant que j'expose, j'attends vous réactions.

Alors on a cerné depuis le début , on a une solution, et on te la donne pour la deuxième fois et on attend que le débutant ait la réaction de lire ce qu'on lui dit.

donc tu écris

ImprimerFonction extends CosMoinsNommee

comme calculer est implémentée dans CosMoinsNommee, ImprimerFonction en hérite et donc tu n'as pas besoin de l'implémenter à nouveau.
Et comme CosMoinsNommee dérive de FonctionNommee, AUTOMATIQUEMENT ImprimerFonction dérive de FonctionNommee comme on te le demande dans l'énoncé.

voilà voilà :twisted: :twisted:

Je te l'ai dit dès le début, et tout le reste était une discussion sur le caractère très mauvais de l'énoncé. Mais bon là je ne vais pas répéter hein... :twisted:

fredericmazue

Ah un dernier mot.
Je ne trouve pas normal que dans FonctionNomme il y ait une méthode "imprimer" et que dans ImprimerFonction on ait "lister" et non pas "imprimer" :lol: Dans une classe qui doit s'appeler ImprimerFonction et qui doit dériver de FonctionNomme, laquelle comporte une méthode imprimer, on s'attend légitimement à trouver une redéfinition de imprimer dans ImprimerFonction, tu ne crois pas :?: :lol:

dav79

Si tu as tout à fait raison fredericmazue concernant ta dernière remarque, l'organisation des classes n'est pas logique

En fait je viens de m'aperçevoir que j'ai fait une erreur dans la lecture du sujet.

J'était perçoidé que ImprimerFonction était une sous-classe de FonctionNommee, c'est à dire avec cette déclaration.

class ImprimerFonction extends FonctionNommee, mais le sujet ne le précise pas explicitement, voici un extrait :

2/ Ecrire une classe nommée ImprimerFonction qui est destinée à lister les valeurs d'une fonction depuis une borne inférieur jusqu'à une borne supérieure avec un pas donné. La classe comportera donc un champ FonctionNommee qui est la fonction à étudier, un champ définissant la borne inférieur, un champ définissant la borne supérieure et un champ définissant le pas. Elle contiendra en plus un constructeur, une méthode appelée lister( ) qui permet d'imprimer les valeurs qu'on veut et la fonction main ( ) dans laquelle on fera une application avec un objet CosMoinsNommee.

Donc tu as raison, je vais déclaré ImprimerFonction en sous-classe de CosMoinsNommee, comme ça le problème sera reglé.

Désolé aussi, j'ai peut être un peu lu vos réponses trop rapidement, je m'en excuse.

En tout cas merci pour l'aide que vous m'avez apporté.

dav79

fredericmazue

Quote:
En fait je viens de m'aperçevoir que j'ai fait une erreur dans la lecture du sujet.

Hum, je crois que tu es encore dans l'erreur...
Quote:
class ImprimerFonction extends FonctionNommee, mais le sujet ne le précise pas explicitement

Voilà qui me rassure quant à la valeur du sujet :)

Quote:
Donc tu as raison, je vais déclaré ImprimerFonction en sous-classe de CosMoinsNommee, comme ça le problème sera reglé.

Non :!:
Si tu fais une sous classe *ton* problème tel que tu as dit l'avoir rencontré dans ton premier message sera réglé. Mais si tu lis bien ton énoncé, je ne pense pas que c'est ce qu'il faut faire.

Quote:
La classe comportera donc un champ FonctionNommee qui est la fonction à étudier

Je t'avais parlé, pour une bonne conception, d'une classe "Fonction" qui détenait un membre ImprimerFonction pour imprimer des résultats.
Je crois que l'énoncé te demande la même chose, mais dans l'autre sens ce qui est correct aussi. C'est à dire une classe ImprimerFonction (qui dérive de rien de particulier donc) et qui a un membre "FonctionAImprimer" de type FonctionNommee et qui pourrait être par exemple CosMoinsNommee. Et ImprimeFonction appelle la fonction calcule de la classe qui dérive de FonctionNommee (par exemple CosMoinsNommee) pour imprimer.

En terme de programmation cette façon de faire s'appelle le Desing Pattern Strategy.

Un peu de (pseudo) code pour te fixer les idée:


class CosMoinsNommee extends FonctionNomme
{
  public double calculer(double x) { /* je calcule y en fonction de x *:}
}

class ImprimeFonction
{
  private FonctionNommee fn = new CosMoinsNomme(); // car tout ce qui dérive de FonctionNommee est du type de la class abstraite :)
  private double bornesup, borneinf // à initialiser

  public void lister() {/* j'imprime/liste ce qu'il faut en fonction de borneinf et bornesur et du résultat de fn.calculer(); */}
}

C'est tout simple :) Kapito ?