2009-05-19 7 views
1

J'ai une classe et je veux changer le nom d'une méthode spécifique en cours d'exécution. Je suppose qu'il existe une méthode dans la classe 'Behavior' qui le fait. Mais je ne peux pas le trouver. de l'aide? [dans squeak]Comment changer dynamiquement le nom d'une méthode dans squeak?

+0

Cela semble un peu ... inhabituel. Pouvez-vous décrire le problème que vous résolviez lorsque vous pensiez qu'une partie de la solution incluait ce problème? En d'autres termes, faites apparaître une étape dans la pile de contexte et exécutez ce que vous essayez vraiment de faire. –

Répondre

2

La manière normale d'un utilisateur est de modifier la source de la méthode et de l'accepter, puis de supprimer l'ancienne version. Donc, il est peu probable que Squeak de base inclue une seule méthode pour le faire, bien que je puisse me tromper.

Cependant, si vous installez, par exemple, OmniBrowser, il existe une méthode de refactoring appelée «renommer» et vous pouvez inspecter et trouver du code pour effectuer ce refactoring. C'est assez complexe, d'abord parce que les refactorings sont faits en utilisant le pattern de commande qui implique une petite redirection, mais ensuite parce que c'est un refactoring assez complexe qui inclut la modification des sites d'appels.

2

Ce que vous suggérez met des drapeaux rouges ÉNORMES pour moi. Qu'est-ce que vous essayez d'accomplir avec ceci?

Voulez-vous dire que vous voulez changer le nom de la méthode que vous appelez lors de l'exécution? Si oui, c'est facile.

faire quelque chose comme:

|methodName| 
methodName := self useMethod1 ifTrue: [#method1 ] ifFalse:[ #method2 ]. 
self perform: methodName. 
+0

#perform: a définitivement sa place, mais il devrait certainement élever des drapeaux en soi! –

0

Évitez la magie voodoo dans le code réel lorsque cela est possible. Cela étant dit, vous pouvez faire des choses très intéressantes en manipulant les méthodes dynamiquement. Par exemple, les briques de code dans Etoys sont traduites en méthodes Smalltalk. D'autres implémentations DSL peuvent également bénéficier d'astuces de métaprogrammation similaires.

Après avoir expérimenté un peu, je suis venu avec le code suivant pour renommer les méthodes unaire:

renameMethod: oldMethod inClass: class to: newMethod 
| oldSelector newSelector source parser | 

oldSelector := oldMethod asSymbol. 
newSelector := newMethod asSymbol. 
oldSelector = newSelector ifTrue: [^self]. 

"Get method category" 
category := (LocatedMethod location: class selector: oldSelector) category. 

"Get method source code" 
source := class sourceCodeAt: oldSelector. 

"Replace selector in method source" 
(parser := class parserClass new) parseSelector: source. 
source := (newSelector asString), (source allButFirst: parser endOfLastToken). 

"Compile modified source" 
class compile: source classified: category. 

"Remove old selector" 
class removeSelector: oldSelector 

Vous pouvez probablement trouver un moyen plus facile de le faire si vous parcourez le code Squeak un peu plus longtemps que moi .

1

Vous mieux utiliser un refactoring

r := RenameMethodRefactoring 
    renameMethod: #foo:foo: 
    in: Foo 
    to: #bar:bar: 
    permutation: (1 to: #foo:foo: numArgs). 
r execute. 
0

Vous ne pouvez pas changer le nom d'une méthode, vraiment, parce qu'il ne possède pas.

Le dictionnaire de méthodes d'un objet mappe des symboles à CompiledMethods. "Changer le nom d'une méthode" signifie "déplacer la valeur CompiledMethod de cette clé vers cette clé".

Questions connexes