12

私は 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

より具体的には、標準の Squeak/Pharo またはその他の smalltalk の実装で、これを可能にするための実質的な構造やコードを追加することなく、これが可能かどうかというのが私の質問です。つまり、Smalltalk に存在する通常のリフレクション機能を備えた言葉です。

例として、メソッドの追加、メソッドの削除、新しいコードのクラスへのコンパイル、インスタンス変数の変更などは可能ですが、単一のオブジェクトを拡張する方法は見つかりませんでした。

Test addInstVarNamed: #var.
Test compile: 'var ^var'.
t:= Test new.
Test instVarNames.
t instVarNamed: #var put: 666. 
t var. #=> 666

答えが「いいえ」の場合は、その理由を説明してください。私はこの問題を解決しようとしているのではなく、それが smalltalk にない理由を理解しているのです。

4

6 に答える 6

11

Smalltalk でインスタンス固有の動作を行うには、基本的に、ポインター クラスとプリミティブ呼び出しを変更する必要があります。The Smalltalk Report、Volume 2#9、1993 年 7 月から 8 月に掲載された、Bob Hinkle、Vicki Jones、および Ralph E. Johnson による「オブジェクトのデバッグ」記事には、すべての説明が含まれています。

1995 年に Bob Hinkle によって VisualWorks 2.0 用にリリースされたバージョンから、元の軽量クラスコードを移植しました。VisualWorks ソースには、 「ParameterizedCompiler」「Breakpoint」、および「Lightweight」という名前の 3 つのパッケージに分割されたコードが含まれています。この分割の理由は、個別の再利用可能な機能を持たせたいという欲求から生まれました。それらのすべては、OOP ジャーナルに個別の記事を持っています。

私のSqueak/Pharo ポートには、 OmniBrowser (および詳細なドキュメントはこちら) フレームワークに基づいた「インスタンス ブラウザ」が含まれています。最新の Squeak 4.x バージョンでは、ほとんどまたはまったく労力をかけずに動作します。残念ながら、Pharo のインフラストラクチャはバージョン <= 1.2 から大幅に変更されたため、最新バージョンで動作させるには何らかの作業が必要になる場合があります。

インスタンスが変更されたインスタンス ブラウザ

VisualWorks では、VisualWorks GUI が 2.0 から 7.3 に大幅に変更されたため、軽量クラスを管理するツールのほとんどが含まれていませんでした。誰か興味があれば、VW 7.3 の小包をアップロードできます

VisualWorks のインスタンス ブラウザ

軽量クラスの機能をテストするための基本的なスクリプトは次のとおりです。

| aDate |
aDate := Date today.
aDate becomeLightweight.
aDate dispatchingClass 
        compile: 'day ^42' 
      notifying: nil 
         ifFail: [self error].
aDate day inspect
于 2013-01-07T19:16:31.723 に答える
8

Smalltalk には、そのようにインスタンス固有の動作を行う組み込みの方法はありません。Smalltalk は、各オブジェクトがクラスに属し、その動作と状態の形状がクラスに依存するという原則に従います。そのため、クラスを簡単に変更できますが (inst 変数の追加、新しいメソッドのコンパイルなど)、そのすべてのインスタンスの動作を変更する必要があります。ただし、軽量クラスなど、インスタンス固有の動作を実現するためのさまざまなアプローチ (Smalltalk フレーバーによる) があります。軽量クラスでは、特定のインスタンス用に特別な (軽量) クラスを作成し、元のクラスをカスタム クラスに置き換えることが考えられます。 1。その結果、「特別な」インスタンスごとに特別なクラスが作成されます。Digitalk StのAFAIKによると、ディスパッチメカニズムはもう少し柔軟で、インスタンスベースの動作を簡単に実装できます(4番目のリンクを参照)。役に立つと思われるリンクをいくつかここに残しておきます。

HTH

編集: Hernan によって投稿されたリンク (Hinkle、Jones & Johnson による「Debugging Objects」) は、私が参照していたもので、見つけることができませんでした。

于 2013-01-07T13:17:14.327 に答える
5

Squeak Etoys は、オブジェクト固有の動作と状態を多用します。これは「ユニクラス」として実装されます。Etoys オブジェクト (Player クラスのインスタンス) のスクリプトを作成すると、オブジェクトのクラスは「ユニクラス」、つまり独自のメソッドを持つことができる Player の一意のサブクラスに変更されます (Etoys スクリプトに対応)。およびインスタンス変数 (Etoys ユーザー変数に対応)。

他の Squeak ベースのプロジェクトでは、スーパークラスのサブクラスとしてリストされていない「匿名」ユニクラスを使用しています。つまり、これらはシステム ブラウザに表示されないため、ほとんど見えないことを意味します (一方、Etoys スタイルのユニクラスはブラウザに表示されます)。

于 2013-01-08T18:01:44.803 に答える
3

ある同僚が、 Bifrostと呼ばれるPharo Smalltalk 用の新しいリフレクティブ API に取り組んでいます。Bifrost プロジェクトのページを確認できます。

彼のアプローチは、インスタンス固有の適応をその核心に押し込みます。すべては、メタオブジェクトを通常のオブジェクトにバインドして適応させることによって行われます。低レベルのメタオブジェクトは、適切な適応を定義する高レベルの粗粒度のメタオブジェクトに構成できます。たとえば、ターゲット オブジェクトの各呼び出しにかかる時間を測定するプロファイリング メタオブジェクトです。

于 2013-01-08T07:56:46.777 に答える
2

@ewernli が指摘するように、Bifrost は基本的に Smalltalk をオブジェクト中心のリフレクション システムにします。すべての反射的な変更は、クラスとのハイブリッド メカニズムを持つ代わりに、最初にオブジェクトを対象としています。オブジェクト中心のリフレクションに加えて、従来のクラス リフレクションをすべて実行できます。この新しいアプローチに関連していると私が考えるのは、ライブシステムの開発方法と認識方法を改善することがわかった多くのアプリケーションです。

オブジェクト中心のデバッグは、ソース コード レベルで条件付きブレークポイントを挿入するのではなく、オブジェクトに集中し、開発者がライブ オブジェクトとやり取りし続けることができるようにすることで、デバッグ方法を完全に変えます。

タレントは、構成可能な動的な再利用の単位です。特性と同様ですが、オブジェクト用です。さらに多くのアプリケーションがあります。

于 2013-01-08T09:41:01.520 に答える
1

Ruby では、私が知る限り、メソッド ディクショナリはオブジェクトにアタッチされます。

Smalltalk では、メソッド ディクショナリはClassオブジェクトにバインドされているため、通常の Smalltalk イメージでは、固有クラスのようなものを書くことはできません。

そうは言っても、いくつかのプロトタイプ ライブラリがあります。この質問の回答では、かなりの数が言及されています。

于 2013-01-07T13:26:47.473 に答える