Reflection 在Pharo Smalltalk中重构方法并创建具有不同名称的副本?

Reflection 在Pharo Smalltalk中重构方法并创建具有不同名称的副本?,reflection,metaprogramming,smalltalk,pharo,Reflection,Metaprogramming,Smalltalk,Pharo,我正在尝试重构和一些自定义功能。有没有办法将方法复制到与原始方法相同的类中,但使用新名称?(本质上是创建一个非常浅的副本)您可以通过编辑方法源手动完成这项工作,但是可以通过编程完成吗 例如: doMethodName: anArgument ^ anObject doThat with: anArgument 变成: doNewMethodName: anArgument ^ anObject doThat with: anArgument 您可以通过向目标类发送compile:消息来编译方

我正在尝试重构和一些自定义功能。有没有办法将方法复制到与原始方法相同的类中,但使用新名称?(本质上是创建一个非常浅的副本)您可以通过编辑方法源手动完成这项工作,但是可以通过编程完成吗

例如:

doMethodName: anArgument
^ anObject doThat with: anArgument
变成:

doNewMethodName: anArgument
^ anObject doThat with: anArgument

您可以通过向目标类发送
compile:
消息来编译方法

  • 检索该方法
    • e、 g.
      方法:=Float>#cos
      方法:=Float方法命名:#cos
  • 检索源代码

    • 方法源代码
      将以字符串形式返回方法代码
    • method ast
      (或
      method parseTree
      )将以解析树表示形式返回代码
  • 将代码编译成类(可选使用协议)

    • TargetClass编译:源代码
      ,或
    • TargetClass编译:源代码分类:协议
  • 所以如果你有

    Something>>doMethodName: anArgument
        ^ anObject doThat with: anArgument
    
    你能行

    code := (Something>>#doMethodName:) sourceCode.
    "replace all matches"
    newCode := code copyReplaceAll: 'doMethodName:' with: 'doNewMethodName:'.
    "or just the first"
    newCode := code copyWithRegex: '^doMethodName\:' matchesReplacedWith: 'doNewMethodName:'.
    Something compile: newCode.
    
    使用AST
    sourceCode
    以字符串形式返回代码,这不是最好的操作方式。 如果您只想更改方法名称,可以在AST中重命名它,例如

    tree := (Something>>#doMethodName:) parseTree.
    tree selector: 'doNewerMethodName:'.
    Something compile: tree newSource.
    

    我还希望,复制方法是标准重构操作的一部分。AST方法非常酷,如果在源代码中使用相同的方法调用,我认为带有简单替换的方法也会替换源代码中的内容。@unmercea我添加了一个regex变量,仅替换第一个匹配项。手动替换字符串通常更容易。使用AST通常更健壮。
    methodSelector:=自类编译器parseSelector:sourceCode。
    如果您希望下一步查找/替换选择器,则可以方便地提取选择器。AST方法确实更好,但对于基于一些外部数据的大量方法的快速脏生成器,例如,
    stream:=WriteStream on:String new。流nextPutAll:(“{2}”处的“{1}^privateProperties.”格式:{accessorName.key});cr.sourceCode:=流内容。
    然后编译速度快,效果好。#asValidSelector还可以将蹩脚的输入转换成一个不错的选择器。