Salut
Je cherche à ajouter des méthodes à une instance de classe, après sa création.
J'ai par exemple
un fichier moto.py
def tourner():
tourner_guidon();
un fichier voiture.py
def tourner():
tourner_volant()
un fichier main.py
class Vehicule():
def __init__(self, categorie):
pass
v = Vehicule('moto')
if v.categorie == 'voiture':
# attacher voiture.tourner()
elif v.categorie == 'moto':
# attacher moto.tourner()
#Pour tourner
v.tourner() # Sans me soucier de la catégorie de véhicule
J'espère être clair….
Et non, ce n'est pas un exercice de cours….
Merci.
David.
# Prendre le problème à l'envers
Posté par Obsidian . Évalué à 7.
Salut,
Même en ayant l'habitude des langages (pré-)compilés où ce genre de manip' est impossible, ajouter dynamiquement des méthodes à une classe est déjà douteux, mais les ajouter à une instance précise est encore plus tordu. Pourtant, l'exercice aurait pu être intéressant en soi…
Mais dans le cas qui te concerne aujourd'hui, c'est un simple problème de conception objet : il faut définir une classe Véhicule, puis deux classes Voitures et Moto qui dérivent toutes les deux de la classe véhicule.
Ce qui donne :
Dans cet exemple, les classes Voiture et Moto dérivent de Véhicule, mais redéfinissent la méthode « tourner », et c'est cette dernière version qui est donc appelée. En revanche, la classe Autogyre dérive également de Véhicule mais définit une autre méthode sans redéfinir « tourner ». C'est donc la version par défaut héritée de « Véhicule » qui est appelée, et c'est pourquoi on obtient « Véhicule qui tourne » et non « Autogyre qui tourne ».
[^] # Re: Prendre le problème à l'envers
Posté par mxt . Évalué à 2.
Bonjour,
Indépendamment du problème de conception signalé plus haut c'est techniquement faisable:
[^] # Re: Prendre le problème à l'envers
Posté par David . Évalué à 1.
Merci.
Mais je voudrais que "tourner" soient des méthodes pour pouvoir manipuler l'instance.
Je trouvais ça plus élégant que de passer mon objet à une fonction.
[^] # Re: Prendre le problème à l'envers
Posté par NeoX . Évalué à 2.
c'est pourtant bien plus logique, non ?
Faire tourner (voiture) = agir sur le volant
Faire tourner (moto) = agir sur le guidon
[^] # Re: Prendre le problème à l'envers
Posté par totof2000 . Évalué à 2. Dernière modification le 21 janvier 2018 à 16:57.
C'est tout simplement parce que tu vois tous les problèmes comme des clous à planter.
Je suis en train d'essayer de traiter une problématique pur laquelle il serait très pratique de pouvoir modifier à la volée une classe (j'en suis pas encore à l'instance de classe). J'essaie de le faire en python, mais je me rends compte que c'est presque impossible. Le seul langage (que e connaisse car il y en a probablement d'autres) qui me permettrait de le faire serait ruby, ou alors de me passer de l'approche objet.
Alors certes, c'est risqué, je ne le ferais absolument pas en n'importe quelle circonstances, mais dans le cas que je traite (définition des classes à partir de spécifications fournies par un fichier yaml), c'est bien pratique. Il est probablement possible de faire autrement de façon plus classique, mais ça serait beaucoup plus compliqué à implémenter.
[^] # Re: Prendre le problème à l'envers
Posté par totof2000 . Évalué à 2.
Bon : je reformule : il faut remplacer
par
[^] # Re: Prendre le problème à l'envers
Posté par Obsidian . Évalué à 4.
Salut,
Je ne suis pas sûr d'avoir complètement compris ce que tu entendais par là, mais si tu voulais dire « une manière de parvenir à ses fins, indépendamment de la curiosité mathématique », alors non. C'est même plutôt le contraire, si tu relis bien mon commentaire. C'est intéressant dans les langages tels que le Javascript qui sont non seulement interprétés, mais où les objets sont définis et remplis à l'exécution.
Par contre, il est important de ne pas faire tout et n'importe quoi juste pour résoudre le problème, même de façon théorique (ce qui nous ramènerait aux clous à planter). En développement logiciel, je suis assez adepte du « changement de paradigme », c'est-à-dire se laisser la possibilité d'utiliser un jeu de concepts totalement exotiques s'il le faut mais À CONDITION de poser le cadre dès le départ et de ne pas en sortir a posteriori au cours d'un projet, surtout si c'est pour se sortir d'une impasse.
En particulier, il y a beaucoup de gens qui font l'amalgame « classe = objet », alors que le mot « classe » doit en fait s'entendre dans le même sens que « classification du règne animal », par exemple. En ce sens, si tu ajoutes ou retires quelque chose à une classe, alors par définition, ce n'est plus la même classe ! Et ça pose problème avec les objets déjà instanciés.
Plus précisément, si l'on modifie une classe, c'est en fait l'ontologie elle-même que l'on modifie, même si cette ontologie est maintenue grâce à des données définies à l'exécution (et qui sont en fait des méta-données). Ça reste très séduisant en soi, mais c'est pour moi du même niveau que le code auto-généré. Ça n'est à utiliser qu'à partir du moment où tous les concepts initiaux sont parfaitement clairs et que, de là, on sait parfaitement ce que l'on fait.
Et là, il me semblait justement que le message du primo-postant n'avait pas vocation à débattre de ce sujet, mais était bien confronté à un cas de figure fondamental en programmation orientée objet, d'où la réponse qui me semblait être la plus appropriée.
[^] # Re: Prendre le problème à l'envers
Posté par totof2000 . Évalué à 3.
Je pense que sur le fond nous sommes d'accord, mais que je n'ai pas forcément saisi le sens de ta remarque à la première lecture. Je voulais juste préciser que bien qu'en général la modification dynamique d'une classe peu sembler être une mauvaise idée, il ne faut pas être dogmatique et savoir s'adapter aux problèmes à traiter.
C'est grosso mode le cas de figure que j'essaie de traiter. Qui dit méta-données dit méta-programmation, et c'est précisément ce que je tente de faire (et python est assez limité de ce côté).
Tout à fait. Dans mon cas, je n'aurais pas la prétention de savoir parfaitement ce que je fais (pour tout dire c'est plutôt de l'expérimentation), mais ce que je sais, c'est qu'il est évident qu'une approche objet "classique" n'est pasl a solution la meilleure.
[^] # Re: Prendre le problème à l'envers
Posté par freem . Évalué à 3.
Pour répondre à la problématique mot-à-mot de l'auteur, en langage compilé pour modifier le comportement d'un objet selon son instance, j'aurais soit utilisé:
Tout ça pour dire que ce n'est pas un problème de langage compilé, et ce genre de techniques sont très utiles dès lors que l'on implémente des mécanismes de plug-ins, par exemple.
[^] # Re: Prendre le problème à l'envers
Posté par copapa . Évalué à 3.
Un exercice pas bien compliqué puisqu'il suffit d'essayer. C'est sûr que c'est douteux mais il y a plein de scénario ou ce genre de possibilité est utile. Le duck-typing en profite énormément, si une bibliothèque nécessite un objet capable de d'aboyer mais que je suis sûr d'avoir besoin et qu'il est pertinent de l'appliquer à mes canards, rien de plus simple que de faire aboyer mes canards.
Ce n'est pas quelque chose qu'on souhaite croiser en production mais tout le monde n'a pas des problèmes d'ingénierie logicielle à résoudre.
# Merci pour vos réponses
Posté par David . Évalué à 1.
:)
# Difficulté ?
Posté par lolop (site web personnel) . Évalué à 3. Dernière modification le 22 janvier 2018 à 14:06.
Mais la bonne façon de faire (au niveau POO) serait d'avoir une sous-class
Moto
et une sous-classeVoiture
, héritant toutes deux de la classeVehicule
, puis de définir une méthode génériquetourner()
qui est redéfinie dans chaque sous-classe.Un fonction factory pourrait être utilisée pour créer
Moto
ouVoiture
suivant un paramètre catégorie. Tu peux en faire qq chose de dynamique dans lequel les modulesmoto.py
etvoiture.py
vont enregistrer quelque part l'association ente la catégorie et la classe ad-hoc à créer.Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Difficulté ?
Posté par lolop (site web personnel) . Évalué à 2. Dernière modification le 22 janvier 2018 à 14:21.
Complément.
Si tu veux passer l'objet en paramètre à tes fonctions isolées (pour accéder à ses attributs), tu peux utiliser la fonction
partial()
du modulefunctools
, définir un paramètre self dans tes fonctions isolées et faire que l'objet auquel est associé la fonction soit passé comme paramètre). Du genre (pas testé):Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.