是否可以在Smalltalk中扩展单个对象

fro*_*ion 11 reflection smalltalk squeak pharo

我正在研究Smalltalk反射,我想知道是否有可能扩展单个对象,例如在Ruby中可能.对此我指的是只有特定对象响应的选择器.

这是一些Ruby代码,说明我的意思.为了澄清:在Ruby中,这将为此对象打开一个虚拟类,并使用新定义对其进行扩展.这里至关重要的部分是类定义没有任何改变!

o = Object.new
o.instance_eval {def foo;puts "foo";end}
o.foo #=> "foo"

#however this will fail:
m = Object.new
m.foo #=> NoMethod error
Run Code Online (Sandbox Code Playgroud)

更具体地说,我的问题是在标准Squeak/Pharo或其他smalltalk实现中是否可行,而不添加实质结构或代码来实现这一点.因此,使用Smalltalk中存在的常规反射特征的其他词语.

例如,可以添加方法,删除方法,将新代码编译到类中,更改实例变量以及任何内容,但我还没有找到扩展单个对象的方法.

Test addInstVarNamed: #var.
Test compile: 'var ^var'.
t:= Test new.
Test instVarNames.
t instVarNamed: #var put: 666. 
t var. #=> 666
Run Code Online (Sandbox Code Playgroud)

如果答案是否定的,那么解释原因.我不是在寻找解决这个问题的方法,而是要理解为什么它不是小问题.

Her*_*nán 10

在Smalltalk中具有实例特定的行为基本上涉及改变指针类和原始调用.Bob Hinkle,Vicki Jones和Ralph E. Johnson 的"调试对象"文章发表于1993年7月至8月的Smalltalk报告第2卷第9期,其中包含所有解释.

我已经从1995年由Bob Hinkle为VisualWorks 2.0发布的版本中移植了原始的Lightweight类代码.VisualWorks源包括分为三个包的代码,名为"ParameterizedCompiler","Breakpoint""Lightweight".这种划分的原因是希望具有独立和可重复使用的功能.所有这些都在OOP期刊上有单独的文章.

我的Squeak/Pharo端口包含一个"实例浏览器",基于OmniBrowser(以及此处的更多文档)框架,它允许您浏览和修改通过经典Smalltalk浏览器UI添加轻量级行为的实例.它可以在最新的Squeak 4.x版本中运行,很少或没有努力.不幸的是,Pharo的基础设施在版本<= 1.2时发生了很大变化,因此可能需要一些工作才能使用最新版本.

实例浏览器修改了实例

在VisualWorks中,由于VisualWorks GUI从2.0到7.3的深层变化,大多数管理轻量级类的工具都没有包含在内.如果有人有兴趣,我可以上传大众7.3的包裹

VisualWorks中的实例浏览器

测试轻量级类功能的基本脚本是:

| aDate |
aDate := Date today.
aDate becomeLightweight.
aDate dispatchingClass 
        compile: 'day ^42' 
      notifying: nil 
         ifFail: [self error].
aDate day inspect
Run Code Online (Sandbox Code Playgroud)


And*_*ier 7

在Smalltalk中,没有以这种方式执行特定于实例的行为的内置方法.Smalltalk坚持每个对象属于一个类的原则,其行为和状态形状取决于类.这就是为什么你可以轻松更改类(添加inst vars,编译新方法等),但这意味着将行为更改为其所有实例.但是,有一些不同的方法(根据Smalltalk风格)用于实现特定于实例的行为,例如Lightweight Classes,其中的想法是为特定实例创建一个特殊(轻量级)类,并用自定义替换原始类一.因此,每个"特殊"实例都有一个特殊的类.Digitalk St中的AFAIK调度机制更灵活,可以轻松实现基于实例的行为(参见第4个链接).我会留下一些你可能会觉得有用的链接:

HTH

编辑: Hernan发布的链接(Hinkle,Jones&Johnson的"调试对象")是我所指的那个,但是找不到.


Ber*_*erg 5

Squeak Etoys 大量使用特定于对象的行为和状态。这是作为“uniclasses”实现的。当你为一个 Etoys 对象(Player 类的实例)创建脚本时,那么该对象的类将被更改为“uniclass”,即 Player 的唯一子类,它可以有自己的方法(对应于 Etoys 脚本)和实例变量(对应 Etoys 用户变量)。

其他基于 Squeak 的项目使用“匿名”单类,它们在其超类中未列为子类。这意味着它们几乎不可见,因为它们不会出现在系统浏览器中,例如(而 Etoys 风格的 uniclass 确实出现在浏览器中)。