【问题标题】:Refactoring methods and creating copies with a different name in Pharo Smalltalk?在 Pharo Smalltalk 中重构方法并创建不同名称的副本?
【发布时间】:2017-01-16 12:15:29
【问题描述】:

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

例如:

doMethodName: anArgument
^ anObject doThat with: anArgument

变成:

doNewMethodName: anArgument
^ anObject doThat with: anArgument

【问题讨论】:

  • 我还希望,Duplicate Method 是标准重构操作的一部分。

标签: reflection metaprogramming smalltalk pharo


【解决方案1】:

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

  1. 检索方法
    • 例如method := Float>>#cosmethod := Float methodNamed: #cos
  2. 获取源代码

    • method sourceCode 会将方法代码作为字符串返回
    • method ast(或method parseTree)将代码作为解析树表示返回
  3. 将代码编译成一个类(可选协议)

    • TargetClass compile: sourceCode,或
    • TargetClass compile: sourceCode classified: protocol

如果你有

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 非常酷,如果它使用相同的方法调用,我认为使用简单替换的那个也将替换源内部的东西。
  • @unmircea 我添加了一个正则表达式变体来仅替换第一个匹配项。手动执行此操作时,字符串替换通常更容易。使用 AST 通常更可靠。
  • methodSelector := self class compiler parseSelector: sourceCode.可以方便地提取选择器,如果您想接下来查找/替换它。
  • AST 方式确实更好,但是对于基于一些外部数据的大量方法的快速而肮脏的生成器,例如stream := WriteStream on: String new. stream nextPutAll: ( '{1} ^ privateProperties at: ''{2}''.' format: { accessorName. key }); cr. sourceCode := stream contents.,然后编译速度很快并且效果很好。
  • #asValidSelector 也可以很好地将糟糕的输入变成一个不错的选择器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多