Bonjour,
Avec ce titre, une explication du contexte s'impose !
J'utilise un package (Shapely pour ceux qui connaissent) qui propose un certain nombre de classes d'objets géométriques : Point, LineString, Polygon , etc.. les noms parlent d'eux-memes.
Il n'est pas exclu, qu'un jour, je veuille en changer. Du coup, je ne souhaite pas utiliser directement ce package dans mes développements plus "haut niveau" mais passer par une "couche intermédiaire". Je la définirai moi-même et je déciderai des évolutions si besoin. Tout changement du package bas niveau ne se répercutera alors "que" dans cette couche intermédiaire (ça ne bavera pas partout).
Pour fixer les idées, je pourrais écrire des classes comme :
- Ponctuel (qui hériterait de Point),
- Lineaire (qui hériterait de LineString),
- Surfacique (qui hériterait de Polygon),
etc...
avec, peu ou prou, les mêmes méthodes que celles déjà existantes. Mais je coince sur le problème suivant.
Plusieurs méthodes, dans chacune des classes Point, LineString, Polygon, ..., prennent, en plus de self, un seul argument (une instance quelconque de ces classes) et renvoient une instance d'une de ces classes. Par exemple :
instance_LineString.intersection(instance_Polygon) peut retourner une instance de Point, de LineString, ..., rien
Si je dérive "bêtement" :
comment retourner des instances de Ponctuel, Lineaire, Surfacique ... et non pas de Point, LineString, Polygon ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class Lineaire(LineString): def intersection(self,other): res = LineString.intersection(self,other) if isinstance(res,Point): # retourner un Ponctuel et pas un Point ! return ... elif isinstance(res,LineString); # retourner un Lineaire et pas un LineString ! return ...
Je peux évidemment créer, pour chaque nouvelle classe, un constructeur qui, à partir d'un Point, construirait un Ponctuel, d'un LineString, un Lineaire, etc... et faire l'instanciation (un "clonage") avant de retourner le résultat mais :
1 - plus les classes sont "compliquées", plus l'instanciation est "lourde"
2 - j'ai parfois de très grands nombres d'objets
Bref, ça m'embête de procéder de la sorte, d'autant plus que "logiquement", les instances créées seraient "quasiment identiques" aux originaux.
J'ai bien essayé la solution "volontariste", en réaffectant brutalement __class__ et les différentes méthodes dans le constructeur, ça semble "marcher" mais je trouve cela un peu "bricolage".
Auriez-vous des idées ? Faut-il chercher du côté des décorateurs ? des méta-classes ? j'avoue avoir atteint mon niveau d'incompétence !
ps : petite précision qui a, peut-être, son importance : toutes les classes Point, LineString, Polygon, ... du package de base sont dérivées d'une même classe
Partager