6

Smalltalkの基礎を学んでいます。superサブクラスメソッド内のスーパークラスからメソッドを呼び出すために使用されるキーワードがあります。

Object subclass: # A
   test
      ^1

A subclass: # B
   test
      ^2
   callSuper
      ^super test

したがってB new callSuper、に評価され1ます。

わかった。それは明らかです。

だから今、私はクラスのクラスメソッドの束を定義していますB

createNew1
    ^super new
createNew2
    ^self new
create
    ^self
createSuper
    ^super

そして、それぞれ、、、およびエラーに評価されa Bます(これは、サブクラスへのキャストではなく、一種のメッセージディスパッチャーであることを示していa Bます)。Bsuper

キーワードにBもかかわらずクラスのインスタンスを取得するのはなぜですか?そして、とオブジェクトsuperの違いは何ですか?オブジェクトはクラスの特別なシングルトーンインスタンス(属性が他の言語で実装されているのと同じように)だと思い始めましたが、それでも-チェックしたところ、クラスはaで、サブクラスはです。a BBBstaticBBA

superクラスメソッドのキーワードのセマンティクスは何ですか?オブジェクトメソッド内のセマンティクスとどのように異なりますか?selfクラス内メソッドを呼び出すことで取得できるオブジェクトは本当に何ですか?

4

5 に答える 5

4

最初の例に対するあなたの答えは間違っています。B new callSuper1を返します。Lukasは、superのセマンティクスの正確な定義を提供しました。これは基本的に「self」のエイリアスであり、送信されるメッセージのメソッドルックアップを変更します。self messageレシーバーのクラスでメソッドのsuper message検索を開始し、式を含むメソッドを定義するクラスのスーパークラスで検索を開始しますsuper message(したがって、この場合、レシーバーのクラスは関係ありません)。

2番目の例super newself newは、同じメソッド(Behavior階層のどこかで定義されている)を呼び出すことになります。これは、どちらの場合もnewのメソッド定義に最も近いためです。ただし、createNewメソッドの名前をnewに変更した場合は、Behaviorメソッドを呼び出すのnew ^self newに対し、無限ループになります。new ^super new

于 2012-06-03T23:44:00.650 に答える
4

selfsuper常に同じオブジェクト、現在のレシーバーを参照します。唯一の違いは、レシーバーのクラスとメソッドが定義されているスーパークラスでself次のメソッド送信のルックアップを開始することです。super

詳細については、 PharobyExampleの第5章を参照してください。

于 2012-06-03T22:09:22.580 に答える
3

クラスはオブジェクトであるため、selfとsuperは、クラスでもオブジェクトでも同じことを意味します。

#createNew1と#createNew2は同等です。Lukasが説明したように、superは単に「クラスではなくスーパークラスでメソッドルックアップを開始する」ことを意味します。AとBのどちらでも#newを定義していないので、スーパークラスを調べて、最終的にBehavior >>#newを見つけます。AとBのどちらから始めても#newは、#basicNewを呼び出すことから始まります。 Bの新しいインスタンス(つまり「aB」)。

#createと#createSuperでは、何も検索していないため、selfとsuperは再び同等であり、「現在のオブジェクトを返す」ことを意味します(後者についてはどのようなエラーを参照していましたか?)。今、この部分は混乱しています。Smalltalkのすべてがオブジェクトであるため、これにはクラス自体が含まれます。したがって、このコンテキストでは、「現在のオブジェクト」はBであり、これはメタクラス「Bクラス」の唯一のインスタンスです。あなたが本当に理解に興味があるなら、私はそれが意味をなすまで何度も何度もPharo ByExampleの第13章を読むでしょう(私はまだその点に到達していません、笑)。

于 2012-06-04T03:10:15.443 に答える
2

他のすべての答えは技術的に正しいにもかかわらず、私は自分でこれに答えるつもりです。これは、メタクラスについて知っていてsuper、頭の中で適切なセマンティクスを持っているように見えますが、それでも予期しない結果が得られていたためです。

Smalltalkの継承の基礎と、メソッドの呼び出し方法を誤解していることがわかりました。

私はそのようなコードのためにそれを考えていました...

Object subclass: #A
    test
        ^'A'
    getTest
        ^self test

A subclass: # B
    test
        ^'B'
    runTest
        ^super getTest

...式B new runTestは次のように評価されます'A'-つまり、スーパークラスのメソッドはアップキャストされたオブジェクトで評価されます。

しかし、そうではありません。

'B'アップキャストがなく、スーパークラスメソッド内でメソッドを呼び出すと、評価されます。検索は、評価されたメソッドの元のクラスではなく、オブジェクトの実際のクラスで開始されます。

その結果、とを呼び出す^self newことは、どのクラスでも^super new定義していませんnewが、同じ効果があります。どちらも、のコンテキストでBehaviourの new実装を呼び出すことになりますself

于 2012-06-04T08:15:28.047 に答える
0

はい、理解できたと思います...
Bクラスから^super newを送信しても、メッセージはBクラスに送信されますが、メッセージは(super new)であるだけです... したがって
、Bのインスタンスを作成します。
もちろん、あなたが定義するなら

A class>>new
    ^A basicNew
于 2012-06-04T21:21:17.493 に答える