2009-05-19 2 views
1

У меня есть класс, и я хочу изменить имя определенного метода во время выполнения. Я думаю, что есть метод в классе «Поведение», который делает это. Но я просто не могу его найти. любая помощь? [in squeak]Как изменить имя метода динамически в squeak?

+0

Это кажется немного ... необычным. Можете ли вы описать проблему, которую вы решаете, когда считаете, что часть решения включает эту проблему? Другими словами, вы увидите шаг в стеке контекста и запустите то, что вы действительно пытаетесь сделать. –

ответ

2

Обычный способ, которым пользователь выполняет это, - изменить источник метода и «принять его», а затем удалить старую версию. Поэтому маловероятно, что базовый Squeak включает в себя единственный метод для этого, хотя я мог ошибаться.

Однако, если вы устанавливаете, например, OmniBrowser, существует метод рефакторинга, называемый «переименование», и вы можете проверить и найти код для выполнения этого рефакторинга. Это довольно сложно, во-первых, потому что рефакторинг выполняется с использованием шаблона команды, который требует небольшого перенаправления для разработки, а во-вторых, потому что это довольно сложный рефакторинг, который включает в себя изменение сайтов вызова.

2

Что вы предлагаете, для меня ставятся ОГРОМНЫЕ красные флаги. Что вы пытаетесь сделать с этим?

Вы хотите изменить название метода, который вы вызываете во время выполнения? Если так, это легко.

сделать что-то вроде:

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

#perform: определенно имеет свое место, но он должен обязательно поднять флаги сам по себе! –

0

Избегайте вуду магии в реальном коде, когда это возможно.

Это, как говорится, можно сделать очень интересные вещи, манипулируя методами динамически.

Например, кирпичи кода в Etoys переведены в методы Smalltalk. Другие реализации DSL также могут быть полезны при использовании подобных метапрограммирующих трюков.

После экспериментов немного я придумал следующий код для переименования одинарных метод:

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 

Вы могли бы найти более простой способ сделать это, если вы просматриваете код Squeak немного больше, чем я ,

1

Вы наилучшим образом использовать рефакторинга

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

Вы не можете изменить имя метода, в самом деле, потому что он не один.

Словарь метода объекта отображает символы в CompiledMethods. «Изменить имя метода» означает «переместить значение CompiledMethod из этого ключа в этот ключ».

Смежные вопросы