Salutations,
Je réalise actuellement un bout de programme destiné à faire un peu de calcul formel (écrire des équations sous forme d'arbre et les résoudre, très classique donc).
J'ai une interface "Formule" de base qui défini une méthode "calculer", de laquelle héritent les classes abstraites "OperationUnaire", "OperationBinaire" etc... desquelles héritent les classes concrètes "Addition", "Soustration", "Negation" etc...
Ca c'est pour la partie "structurelle" des formules manipulées.
Pour ce qui est des données, j'ai défini une classe abstraite "Valeur" de laquelle héritent les classes concretes "ValeurEntieres", "ValeurFlottante", "ValeurChaine" etc...
Notez également que ces valeurs concrètes implémentent l'interface "Formule", de façons à ce qu'un formule puisse comprendre indistinctement des valeurs (feuilles) ou des opérations (noeuds).
(la raison pour laquelle les valeurs ne sont pas toutes typées de la même manière, c'est pour permettre, a terme, d'avoir des trucs du genre :
if $nom == "thomas" then $code_reduction = 2; (sous forme d'arbre, évidemment))
Imaginons à présent que l'on envisage cette formule :
Formule maFormule = new Addition(new ValeurEntiere(1), new ValeurFlottante(0.7));
Et que l'on effectue par la suite l'appel suivant:
Value resultat = maFormule.calculer();
En interne, la fonction "calculer" d'"Addition" appelle le code suivant :
return (membreGauche.Ajouter(membreDroite)); (avec des notations claires)
En effet, chaque type de valeur surcharge, en interne les méthodes:
public Valeur ajouter(ValeurEntiere v);
public Valeur ajouter(ValeurFlottante v);
// etc...
Or, pour que le compilateur ne gueule pas, j'ai évidemment dû écrire, dans la classe abstraite Valeur (ce qui explique pourquoi ce n'est pas une interface), la méthode
public Valeur ajouter(Valeur v);
qui se contente, a priori, de lever une exception vu qu'il n'est pas possible d'instancier de type d'objet Valeur.
Sauf que, c'est systématiquement cette dernière méthode qui est appelée, et jamais les méthodes plus spécialisées : je pensais que le compilateur routerais la méthode la plus spécifique selon le type de l'objet à l'exécution, mais non : c'est systématiquement la fonction générique qui est appelée...
Et la je vois pas trop comment faire (du moins proprement...)
Alors c'est vrai que la solution la plus simple c'est de conserver cette fonction générique en faisant en sorte qu'elle route l'objet vers la bonne fonction en regardant le type de l'objet à l'exécution, mais les cast de ce type j'ai tendance a trouver ca un peu moche... (même si, implicitement c'est ce que j'aurais voulu que le compilateur fasse en interne)
Bref y a pas vraiment de question, a part si ce problème classique admet une solution propre à laquelle je n'aurais pas pensé.
Merci![]()
Partager