Caching 缓存所有方法的结果
我有一个类,它本质上是一些数据转换方法的集合。换句话说,我的文件中有一些数据,我使用一些不同的代码片段将文本数据转换成我可以轻松查询的内容 现在,这些方法经常相互重用,随着核心数据的变化,出于速度原因,我只想缓存每个方法的结果 我不想通过添加以下内容来更改每个方法:Caching 缓存所有方法的结果,caching,reflection,smalltalk,pharo,Caching,Reflection,Smalltalk,Pharo,我有一个类,它本质上是一些数据转换方法的集合。换句话说,我的文件中有一些数据,我使用一些不同的代码片段将文本数据转换成我可以轻松查询的内容 现在,这些方法经常相互重用,随着核心数据的变化,出于速度原因,我只想缓存每个方法的结果 我不想通过添加以下内容来更改每个方法: ^ methodsCache ifNil: [ methodsCache := "compute" ] 我想使用Pharo反射的强大功能来完成我的任务,而不涉及太多的代码 我的一个想法是,如果我可以在每个方法之前运行一些代码,我可
^ methodsCache ifNil: [ methodsCache := "compute" ]
我想使用Pharo反射的强大功能来完成我的任务,而不涉及太多的代码
我的一个想法是,如果我可以在每个方法之前运行一些代码,我可以返回一个缓存的值,或者继续执行该方法并缓存其结果
doesNotUnderstand: aMessage
aMessage selector beginsWith: 'cached' ifFalse: [ ^ super doesNotUnderstand: aMessage ].
^ cache at: aMessage selector ifAbsentPut: [
self perform: aMessage selector allButFirst: 6 ]
这样,您唯一需要做的就是将所有消息发送(如
self-methodName
)替换为self-cachedmethodName
(或self-cachedmethodName
),然后您必须在doesNotUnderstand:
中执行其他小写操作您可以使用Reflective框架向方法中添加前置和后置元链接。链接可以在执行前透明地检查缓存
link := MetaLink new
metaObject: self;
selector: #cachedExecute:;
arguments: #(selector);
control: #before.
(MyClass>>#myMethodSelector) ast link: link.
此代码将安装一个元链接,该链接将#cachedExecute:
发送到带有参数#myMethodSelector
的MyClass
对象。链接安装在已编译方法的第一个AST节点上(属于同一个方法选择器,但可能位于另一个方法上)。#control:
消息确保在执行AST节点之前执行链接
当然,您可以安装多个相互影响的元链接
请注意,在上面的示例中,不能在#cachedExecute:
方法中再次发送相同的消息(#myMethodSelector
),因为这样会在循环中结束
更新
上面的代码中实际上有一个错误(现已修复)。
#arguments:
消息包含一个符号列表,这些符号定义了通过#选择器:
指定的方法的参数。这些论点将从上下文中具体化。要传递方法选择器,您需要使用#选择器
具体化,方法上下文使用#上下文
具体化,方法参数使用#参数
。要查看哪些具体化可用,请查看rfreifyization
子类的类侧的#键
,另一个众所周知的选项是替换新的并返回缓存代理,委托给实际对象,谢谢Max,这是一个非常好的示例。您知道如何重定向方法的参数吗?另一个问题是如何执行cachedExecute:
?我可以调用我的方法的“干净”版本吗?我可以返回一些值而不是运行方法的其余部分吗?您可以在缓存方法执行后在同一方法上安装#after
链接,而不是链接。而#
链接将返回缓存的值(它将替换方法的整个AST)。