geniacllm/wiki40b huggingface dataset:
中間言語を実行している仮想機械も一般的には Smalltalk で記述される。ただし、仮想機械で動く Smalltalk の実行イメージが実行環境の機械語で直接動作する仮想機械にはなれないため、Smalltalk で書かれたソースコードを一度Cのソースコードに変換し、C言語のソースコードから実行環境で直接動作する仮想機械を生成するという形式をとっている。Smalltalk の実行環境が全く存在しない初期の状況ではコンパイラーも仮想機械も Smalltalk で用意する事はできない。このため Smalltalk の初期段階ではALTOのアセンブリ言語によりコンパイラーや仮想機械が実装されていた。
オブジェクトの内部構造を再帰的に表示するツールである。また、多くの場合オブジェクトの編集が可能でありWorkspaceと組み合わせてオブジェクトを組み立てていくことが可能である。例えば画面部品をWindowを表すオブジェクトに組み込み、クラス変数に格納するといった具合である。Inspectorに限らずSmalltalk環境全体に共通することであるが、オブジェクト内の変数を表示するときは内部構造そのままではなくオブジェクトの文字列表現で表示する。このため内部がHash map等複雑な構造になっている場合でもDictionary (#key -> 'value' )といった読み易い表示となる。
Smalltalk の言語仕様は原則として非常に単純なため、環境もしくは処理系の相違による互換の有無は、クラスライブラリーの差異程度に由来するもの（ある意味、バージョンの違いもこれも含まれる）から、言語仕様自体の改変に由来のものまで空間的に連続で多岐にわたる。このため、単に Smalltalk として語弊のある場合、一般にその環境および処理系の呼称もしくは商標（必要ならそのバージョン）をして他と区別するために用いる慣習がある。
「"～"」のようにダブルクオーテーションでくくった文字列がコメントとして扱われる。
一時変数は宣言が必要で、「|」で挿むように記述する。変数への代入は「:=」。古い処理系では「_」が使用された（字形は「←」）。変数に型はなく全てハンドルになっている。| a b |a := 3.b := 4.
他の言語で予約語にあたる擬変数は self、super、nil、true、false、thisContext の6つ。self と super はそのメソッドを呼び出したメッセージの受け手（レシーバー）を、nil と true と false はそれぞれ UndefinedObject、True、False に属するソルインスタンス（唯一の実体）を、thisContext は実行中のコンテキスト（スタックフレーム）を参照するのに使える。self と super は同種のオブジェクトだが、メッセージ式でメッセージレシーバーに指定されたときのメソッド検索の起点が異なり、self ではオブジェクトが属するクラス、super ではその基底クラスである。
複数の式を順次実行する場合は、式をピリオドで区切る。メソッドを中断し戻り値を指定するには復帰文「^ 戻り値式」を使う。言語機能として持つ制御構文は復帰文を除いて存在せず、復帰文以外の制御は制御構文と同等の機能を持ったメッセージ式で代用する。
ブロックは、他の言語で言えば無名関数やクロージャーに該当する機能である。ただし Smalltalk のブロックは関数ではなくオブジェクトである事に加え、無名関数というより制御構文としての性格が強くなっている。並列実行の基本単位にもなる。ブロックは、引き数の数毎に複数定義された「value」を含むメッセージを送る事で、ブロック内に記述されたメッセージ式を実行し結果を返す。[                 　0               ] value.             "-> 0"[ :value1         | value1          ] value: 1.          "-> 1"[ :value1 :value2 | value1 + value2 ] value: 1 value: 1. "-> 2"ブロック内の:value1 :value2は引き数であり、「|」以降は「value」を含むメッセージが送られた際実行するメッセージ式である。「value」を複数ならべたセレクターは4個程度まで( #value:value:value:value: )しか定義されておらず。5個以上引き数を取る場合は、配列を引き数とする#valueWithArguments:を使う必要がある。メソッドが値を返す際は、復帰文の記述が必要となるがブロックの場合は値を返すのに復帰文は必要ない。最後に実行されたメッセージ送信の結果あるいは、最後に書かれた値が戻り値となる。ブロックは制御の基本となるオブジェクトであるため、「value」を含むメソッド以外にも膨大なメソッドを持っている。ただし、後述する他の制御構文はブロックに対し#valueセレクターまたは、#value:セレクターを使ったメッセージしか送らない。ブロックにはvalueと合わせてよく使われるセレクターとして「cull」がある。cullの振る舞いは、ほぼvalueと同じであるが、ブロックがメッセージに含まれる引き数を無視できるという違いがある。[ :value1 | value1 ] cull: 1 cull: 2. "-> 1"cullはブロックによる分岐制御が主目的であるが、分岐の基準になったオブジェクトを参照する場合もあるようなセレクターで使われる。典型的な例は、オブジェクトがnilで無いときだけブロックを実行する#ifNotNil:である。| block value1 value2 |block := [ :value | value ].value1 := 1.value2 := 2.value1 ifNotNil: [ 9 ]. "-> 9"value1 ifNotNil: block. "-> 1"value2 ifNotNil: block. "-> 2"
条件分岐は #ifTrue:ifFalse: セレクターを用いたメッセージ式として、条件式の結果の真偽値へのメッセージ送信の形で次のように記述する。3 < 4 ifTrue: [ 5 ] ifFalse: [ 6 ].Smalltalk では nil がオブジェクトである。これを利用した nil 専用の条件式も存在する。object := nil.object ifNil: [ 5 ] ifNotNil: [ 6 ].object ifNotNilDo: [ :value | value inspect. ].条件分岐の制御において、他の言語でいうswitchに直接該当する文は存在しない。多態性を利用して分岐するか、次のように連想配列を利用して分岐するため不要である。something: aNumber| switch |"速度が求められる場合は、初期化済みのDictionaryのオブジェクトをインスタンス変数やクラス変数にキャッシュする。"switch := Dictionarynewat: 1 put: [ #a ];at: 2 put: [ #b ];at: 3 put: [ #c ];yourself.^ ( switch at: aNumber ifAbsent: [ #z ] ) value.但し一部の処理系では、次のようなswitchに類似した書き方ができるものも存在する。something: aNumber^ aNumber caseOf:{[ 1 ]->[ #a ].[ 2 ]->[ #b ].[ 3 ]->[ #c ].}.
反復制御においてfor に直接該当する文は存在しない。代わりに回数を指定した反復がある。回数を指定した反復は、整数型へのメッセージ送信の形で次の様に記述する。 "100回の反復処理を実行する"100 timesRepeat:["反復実行する処理"].現在の反復回数を参照しながら反復する事も出来る。 "100回の反復処理を実行する"1 to: 100 do:[ :each |"eachは現在の反復回数"].for　に該当する文は存在しないものの、while に該当する文は存在する。while に該当する反復は、ブロックに対するメッセージ送信の形で次の様に記述する。[ true "真偽値を返す式" ] whileTrue:["反復実行する処理"].#whileTrue: セレクターは、条件が真である間反復する事を意味している。逆に条件が偽である間反復する #whileFalse: というセレクターも存在する。また do-while に該当する文も存在する。do-while に該当する反復は、ブロックに対するメッセージ送信の形で次の様に記述する。["反復実行する処理""このブロックの実行結果が真である間反復を繰り返す"] whileTrue.Smalltalk では条件なしの反復も存在する。無条件反復は、ブロックに対するメッセージ送信の形で次の様に記述する。["反復実行する処理"] repeat.Smalltalk では、反復方法が複数存在するが、実は全てメソッドの再帰呼び出しによって実装されているという事になっている。ただし、こちらも #ifTrue:ifFalse 同様実際にメソッドの再帰呼び出しとして実行されていない事が多い。
C言語の break や Perl の last に相当する反復脱出は thisContext に対し #return セレクターを使ったメッセージを送る。[thisContext return. "反復を抜ける"] repeat.thisContext には、引き数を取り、引き数を脱出するブロックの戻り値として返す #return: セレクターや、戻り先のメソッドを指定する #return:to: セレクターなど多数の return 系セレクターに対応するメソッドが定義されており、他の言語には珍しい多様な反復の脱出方法を備えている。
Smalltalk にも例外処理機構が存在する。こちらも、その他の構文と同じくメッセージ式とブロックによって実現されている。例外処理は次の様に記述する。[[Exception signal: '処理失敗'. "例外発生"]ensure:["例外の有無に関わらず実行したい処理"].]on: Exception "補足する例外の種類"do:[ :exception |"例外を補足した際の処理"].なお#ensure:は後述のブロックによる資源の開放があるため多用されることはない。例外の制御はメッセージ送信毎に連結リストとして積み上げられたコンテキスト情報の末端のコンテキスト（メソッドスタック）を表す thisContext オブジェクトを操作し、コンテキストを巻き戻す事で実現されている。複数の例外は、#on:do:on:do・・とon:do:を繰り返し(処理系が定義している限りの数で)記述して補足する事もできるが、次の様に例外の型を,で並べて補足する事も出来る。[Notification signal: '接続準備完了'. ]on: Error, Notificationdo:[ :exception |"エラーと通知両方の例外を1度に補足"].なお、Smalltalkでは正常な結果を返せないエラー(間違い)と通知両方を合わせたものが例外である。例外は正常な戻り値を返せない場合と割り込みの様に非同期な通知に利用される。
Smalltalkでは、標準で並列処理が存在する。並列処理は次の様に記述する。| process semaphore |semaphore := Semaphore new.process :=[Process yield. "他のProcessに切り替える切り替え点""並列実行される子処理"semaphore signal. "親処理への終了通知"] newProcess.process resume."子処理の起動。Blockに対し#forkを送る場合はnewProcessとresumeは省略できる""並列実行される親処理"semaphore wait. "子処理の終了待機"並列処理はスレッドに類似するプロセスという仕組みにより実装されている。プロセスはSmalltalk環境内で構築された並列処理の仕組みであり、グリーンスレッドで実装されている事が多い。このため、プロセスは論理的に非プリエンプティブなスレッド(グリーンスレッド)を前提しており、現在実行している処理を切り替える切り替え点を必要とする。論理的な前提は非プリエンプティブではあるものの、POSIX環境で動作させたGNU Smalltalkの様に実際はプリエンプティブなスレッドで実装されている場合もある。プロセスは他のプロセスから割り込みとして任意の例外を投げる機能があり(記述方法は環境によって異なる)、切り替え点はプリエンプティブなスレッドを使う場合でも例外の発生地点として機能する。
Smalltalk は、クラスの定義をメッセージ式による実行環境へのクラスオブジェクトの登録として実現する。他の言語と異なりクラスオブジェクトの登録は単なる定義ではなく実行環境に対する操作である。1度クラスオブジェクトを登録してイメージファイルを保存すると、明示的にクラスオブジェクトを削除しないかぎりはクラスオブジェクトがイメージファイルに残り続ける。Smalltalk 環境に対するクラスオブジェクトの登録は次の様に記述する。"DerivedクラスをSmalltalk環境に登録する例"Object"基底クラスオブジェクト"subclass:        #Derived"Objectクラスの派生として登録するクラスオブジェクト名の指定"instanceVariableNames:'ia ib ic'"インスタンス(実体)オブジェクトに所属する変数名(インスタンス変数)の指定(空白区切り)"classVariableNames:    'ca cb cc'"クラスオブジェクトと共有する変数名(クラス変数)の指定(空白区切り)"poolDictionaries:    'pa pb pc'"クラスに所属する変数(プール変数)を取り込む辞書の指定(空白区切り)"category:        'example'."Smalltalk環境上でクラス名を表示する際にクラスが所属する分類の指定"poolDictionaries と category を除いては、C++ から派生した言語のクラス定義と概ね同じである。インスタンス変数はインスタンスメソッドのみから参照でき、クラス変数はクラスメソッドとインスタンスメソッドから参照できる。他の言語と異なりインスタンス変数をクラスメソッドから参照することはできない。Smalltalk におけるクラスの作成は、特殊構文ではなく単なるメッセージ送信である。クラスを登録する際のメッセージは、上記の例のように次のセレクターを使用することが多い。#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:しかし、クラスの登録はあくまでメッセージであり自由に作れるため、実行環境には大抵その他のメソッドが用意されている。例えば、近代的な Smalltalk 環境の一つ Pharo では、次のセレクターに対応したメソッドが用意されている。#subclass:#subclass:category:#subclass:instanceVariableNames:#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:#subclass:uses: #subclass:uses:instanceVariableNames:classVariableNames:poolDictionaries:category:#variableByteSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:#variableByteSubclass:uses:ginstanceVariableNames:classVariableNames:poolDictionaries:category:#variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:#variableSubclass:uses:ginstanceVariableNames:classVariableNames:poolDictionaries:category:#variableWordSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:#variableWordSubclass:uses:ginstanceVariableNames:classVariableNames:poolDictionaries:category:#weakSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:#weakSubclass:uses:ginstanceVariableNames:classVariableNames:poolDictionaries:category:クラスオブジェクトには、クラス変数とは別途、クラスオブジェクトが Class クラスから派生したインスタンスとして状態を持つためのインスタンス変数がある。このクラスオブジェクトのインスタンス変数はクラスオブジェクト内だけで共有され、インスタンスオブジェクトからは直接使用できない。Smalltalk 環境に対するクラスオブジェクトのインスタンス変数の登録は次の様に記述する。Derived class instanceVariableNames: 'ia ib ic'. "クラスオブジェクトのインスタンス変数名(空白区切り)"クラスオブジェクトがもつインスタンス変数には変数を登録した基底クラスと派生クラスで別々の変数領域が確保されるという特筆すべき点がある。これを使用して下記の様にクラスに所属するオブジェクトだけを保持する変数としてつかったりする事ができる。Object subclass: #Super.Super class instanceVariableNames: 'objects'.Super class methodsFor: 'accessing'!objects    ^ objects ifNil: [ objects := OrderedCollection new ].!!Super class methodsFor: 'instance creation'!new    | object |        object := super new.    self objects add: object.    ^ object.!!Super subclass: #Derived. Derived new.Derived objects size. "-> 1"Super objects size. "-> 0"
メソッド（処理方法）の登録は、コード文字列を引数として与えたクラスへのメッセージ送信でも行えるが、通常は環境に組み込まれたクラスブラウザ（システムブラウザ）と呼ばれるGUIツールを用いる。メソッドは、「メッセージパターン」と呼ばれるメッセージ式のメッセージ部分を模した書式に続けて0個以上のメッセージ式を連ねることで記述する。例えば、前出の、レシーバーか引数を比べてより小さな方を返す「min:」というメソッドの登録は次のようなものになる。min: anOtherObject^ self < anOtherObject ifTrue: [ self ] ifFalse: [ anOtherObject ].一行目の「min: anOtherObject」がメッセージパターンで、メソッド名（セレクター）と仮引数となる擬変数の宣言を兼ねる。念のためここでメソッド名は「min:」、仮引数となる擬変数名は「anOtherObject」である。メッセージパターンのあとに処理を続けて書くこともできるが、通常は行を改めて（さらに、ここでは省いたが慣習としてメソッドの説明をするコメントを書き、それに続けて）処理を記述する。なお、メッセージパターンのみで具体的な処理を記述せずにメソッドを登録した場合を含め、復帰文による明示的な戻り値の指定が無い場合、メソッドは戻り値として常に self を返す。したがって Smalltalk では値を返さないメソッドを書くことはできない。
Smalltalkは、多くの動的型付け言語やDelphiの様にクラスがオブジェクトである。このためSmalltalkではインスタンスオブジェクトと同様にクラスオブジェクトを変数に束縛してメッセージを送ることができる。| object |object := Something new.object value. "インスタンスオブジェクトにvalueメッセージを送信"object := Something.object value. "クラスオブジェクトにvalueメッセージを送信"クラスオブジェクトは、オブジェクトにclassメッセージを送ることでも取得できる。' ' class. "-> ByteString"
Smalltalk のブロックは一種の制御構文であるという性質上、復帰文が他の言語と比べ極めて異質な振る舞いをする。example| block |block := [ ^ 1 ].block value. "ブロックを実行"^ 0.上記のメソッドを登録したオブジェクトに#example セレクターを使ったメッセージを送ると結果としては何が返ってくるか。Smalltalk 以外の言語では 0 が返ってくるのが一般的であるが Smalltalk では 1 が返ってくる。Smalltalk はブロック内の復帰文からでもメソッド自体を抜けることができるようになっている。この例では、「block value.」を評価し、block 中の「^ 1.」で制御が戻ると example 自体も中断して結果を返す。そして example は戻り値として block が戻した 1 を戻すようになっている。callee: aBlockaBlock value.^ 2.caller| block |block := [ ^ 1 ].self callee: block.^ 0.上記の様なメソッドをまたいでブロックを評価する場合はどうなるだろうか、この場合も Smalltalk は example の戻り値として block の戻り値である1を返す。Smalltalk はブロック内で復帰文が実行された際、ブロックの生成地点の呼び出し元までコンテキストを巻き戻すようになっている。この特性により Smalltalk では、#ifTrue:ifFalse: セレクターを使った分岐でメソッドを中断したり #repeat セレクター等を使った反復処理を復帰文だけで中断する事ができるようになっている。exampleBlock^ [ ^ 1 ].callee: aBlockaBlock value.^ 2.caller| block |block := self exampleBlock.self callee: block.^ 0.ただし、上記の様にブロックを生成したコンテキストと、ブロックを評価する際のコンテキストが枝分かれする様な場合は復帰文を実行する事はできない。この場合は BlockContext が例外を出力し処理が停止してしまう。
Smaltallkでは、Smalltalk環境全体で参照できる大域変数を作成する事が出来る。大域変数は同じく大域変数であるSmalltalk変数に格納されたSmalltalkImageのインスタンスオブジェクトにメッセージを送って作成する。また、大域変数の削除もSmalltalkImageのインスタンスオブジェクトに対するメッセージ送信となっている。Smalltalk at: #GlobalVariable put: 100.GlobalVariable. "->100"globalVariable := 10.Smalltalk at: #GlobalVariable. "->10"Smalltalk removeAt: #GlobalVariable.GlobalVariable. "->nil"SmalltalkImageは一種の連想配列であり、Smalltalkの大域変数は、Smalltalk変数を介す事で連想配列として操作する事が出来るようになっている。なお、Smalltalkのクラス名と大域変数は同じものであり、クラス名にオブジェクトを代入すれば、そのクラスを破壊してしまうことが出来る。また、Smalltalkオブジェクトが格納されたSmalltlak変数もオブジェクトを代入し破壊する事が出来る。このように大域変数を代入により破壊してしまった場合は、最悪Smalltalk環境が起動しなくなる事態に陥り非常に危険である。このためSmalltalkではよほどの理由がなければ大域変数を使うべきではない。
プール辞書は、クラスの変数として連想配列または、他のクラスオブジェクトのクラス変数を取り込むという機能である。取り込む連想配列の要素やクラスオブジェクトのクラス変数はプール変数と呼ばれる。連想配列やクラスオブジェクトは大域変数でなくてはならない。"プール辞書で使用する連想配列の登録"Smalltalk at: #UserPoolA put: Dictionary new.UserPoolA at: #ExamplePoolValueA put: 1."プール辞書で使用するクラスオブジェクトの登録"Objectsubclass:#UserPoolBinstanceVariableNames:''classVariableNames:'ExamplePoolValueB'poolDictionaries:''category:'example'."UserPoolAとUserPoolBをプール変数として利用するクラスオブジェクト"Objectsubclass:#SomeoneinstanceVariableNames:''classVariableNames:''poolDictionaries:'UserPoolA UserPoolB'"UserPoolAとUserPoolBを辞書に記述しプール変数を取り込む"category:'example'.Someone methodsFor: 'accessing'!valueA^ ExamplePoolValueA. "UserPoolAのExamplePoolValueAを参照"!valueB^ ExamplePoolValueB. "UserPoolBのExamplePoolValueBを参照"!!プール辞書には複数の連想配列やクラスオブジェクトを指定できるが、プール変数が重複した場合は、先に指定した連想配列やクラスオブジェクトのプール変数が使われる。
Pharo, GNU Smalltalkといった近代の環境では、定数以外に式の結果を指定可能な非定数要素の配列定数を使用できる。配列の要素は空白ではなく.で区切る。array := { 1. 1 + 1 }. "1と2を要素に持つ配列を作る。"
継続渡し形式を支援する機能として継続があり、PharoやGNU Smalltalkで使用できる。もっぱら反復の中断や、メソッド内の処理を飛ばすために使われる。継続の使用は次の様に記述する。result := Continuation currentDo:[ :break |aCondition1 ifTrue: [ break value: 1 ]. "aCondition1がtrueなら以降の処理を中断しresultに1を代入する。"aCondition2 ifTrue: [ break value: 2 ]. "aCondition2がtrueなら以降の処理を中断しresultに2を代入する。"3 "aCondition1, aCondition2両方trueならresultに3を代入する。"].
遅延評価を支援する機能として生成器があり、PharoやGNU Smalltalkで使用できる。生成器はCoroutineにも利用できる。生成器の使用は次の様に記述する。stream := Generator on:[ :each |each yield: 1.each yield: 2. "stream nextを1回呼ぶまで実行しない。"each yield: 3. "stream nextを2回呼ぶまで実行しない。"].stream next. "-> 1"stream next. "-> 2"stream next. "-> 3"生成器を使って処理を作ることは多くないが、配列などを使用する際、間接的に使用していることが多い。| readStream grater2 total |readStream := #( 1 2 3 4 5 ) readStream. "#readStreamにより#select:を遅延実行する生成器が作られる。"grater2 := ( ( readStream select: [ :each | 1 < each ] ) collect: [ :each | each * 2 ] ) reject: [ :each | 8 > each ].total := grater2 inject: 0 into: [ :value :each | value + total ]. "#inject:into:でeachに代入するとき初めて#select:と#collect:と#reject:が実行される。"
Smalltalk のプログラムは基本的に中間言語としてイメージファイルの中に格納され、ソースコードの編集は Smalltalk のGUI環境から行われる。このため基本的にファイルという形で Smalltalk のソースコードやプログラムを目にすることはない。しかし、ソースコードの交換目的などでどうしても Smalltalk 環境外でソースコードを管理する必要がある場合に備えファイル用の構文が存在する。ファイル用の構文は次のようになる。Objectsubclass:#ExampleinstanceVariableNames:''classVariableNames:''poolDictionaries:''category:'example'.Example methodsFor: 'Instance Methods A' !selectorA1"処理"^ 0.!selectorA2: anArgument"処理"^ 0.!!Example methodsFor: 'Instance Methods B'!selectorB1"処理"^ 0.!selectorB2: anArgument"処理"^ 0.!!Example class methodsFor: 'Class Methods' !selector1"処理"^ 0.!selector2: anArgument"処理"^ 0.!!本来他の言語の様なブロックが存在しないため、ブロックとして「!」が使用される。クラスの登録は「!」の一組で囲まれる。メソッドはプロトコル毎に「 クラス名 methodsFor: 'プロトコル' ! 〜 !!」というブロックで囲まれる。一つのプロトコルには複数のメソッドを定義でき、メソッド同士は一個の「!」によって区切られる。ちなみに、クラス登録は単なるメッセージ送信であり特別な文ではないため、登録用ブロック外にも次のように単純なメッセージ送信の記述に使用する事が出来る。Example methodsFor: 'Instance Methods A' !selector1!!'hello' displayNl.'world' displayNl.Example2 methodsFor: 'Instance Methods A' !selector!!ファイル用構文で記述されたメソッドの登録は、可読性や記述性の面からメッセージ式からかけ離れた変則的な構文が使用される。しかし、この変則的な構文を用いなければメソッドを登録できないわけではなく、次のように通常のメッセージ式でメソッドを登録する事も出来る。Examplecompile:'selectorC: anArgument^ 0.'classified: 'Instance Methods C'.上記では、クラスオブジェクトExampleのプロトコルInstance Methods Cに対し、メソッドselectorCを登録している。
Smalltalk において、継承とは特殊な委譲に過ぎない。Objectsubclass:#Derived"DerivedはObjectクラスから派生させる"instanceVariableNames:''"オブジェクトに所属する変数は定義しない"classVariableNames:''"クラスオブジェクトと共有する変数は定義しない"poolDictionaries:''"クラスに所属する変数は定義しない"category:'example'."クラスの分類はexampleとする(今回の名前に意味はない)"このため、例えば上記のクラスオブジェクトの生成では、Derived クラスオブジェクトの基底クラスオブジェクトとして Object を指定しているが、処理系によっては下記の様に #superclass: メッセージを送る事で、基底クラスに別のクラスオブジェクトを指定する事が出来る。"superclass: NewBase. メッセージを送り基底クラスを NewBase に変更する事が出来る。"Derived superclass: NewBase.処理系により不可能な事もあるがクラスオブジェクトだけでなく、インスタンスオブジェクトから派生することも出来る。"インスタンスオブジェクトの nil から派生した Derived クラスを Smalltalk 環境に登録する"nilsubclass:#DerivedinstanceVariableNames:''classVariableNames:''poolDictionaries:''category:'example'.なお通常、派生元の基本となるProtoObjectやObjectはnilから派生しており継承関係は再帰的に循環している。
Smalltalk において、メッセージ、セレクター、メソッドはそれぞれ別物である。C++ 系統の言語の様にオブジェクトに対しメッセージを送るという事は単なる比喩ではない。あるオブジェクトに対し #hello というセレクターを使ったメッセージを送る事を考える。この時、Smalltalk においては hello というメソッドが必ず呼ばれる保証はない。例えば「hello」メッセージを受け取るオブジェクトが hello メソッドを実装していなければレシーバーに指定されたオブジェクトの doesNotUnderstand: メソッドが呼ばれる事になる。なお、多くの Smalltalk の処理系では doesNotUnderstand: の引き数で得られたメッセージを返すだけのクラスが用意されている。例えば Smalltalk 環境のひとつである Pharo ではメッセージ作成用クラス MessageCatcher が用意されており次のようにメッセージを拾い、他のオブジェクトに渡すことが出来る。message := MessageCatcher new show: 'text'. "「show: 'text'」がmessageに代入される。"message sendTo: Transcript. "「Transcript show: 'text'」が実行される。"また、セレクターとメソッドが独立していることを利用して一つのメソッドを複数のセレクターに結びつける事もできる。"#onClick:を使ったメッセージをopen:メソッドに転送させる。"FileEventHandleraddSelector:#onClick:withMethod:FileEventHandler >> #open:.メッセージにはセレクターと引き数が含まれている。このため受け取ったセレクターと引き数を編集する事も出来る。message := MessageCatchernewbold: truetext: 'example'.message selector keywords keysAndValuesDo:[ :key :each |        Transcript                show: each, ':=', ( message arguments at: key ) printString;                cr.]."以下が出力される。bold:=truetext:=example"
プログラミング言語一般の概念として型検査をソースコードの翻訳時に実行するか、実行時に実行するかにより静的型付けと動的型付けという区分が存在するが、Smalltalkは、そのどちらでもなく型なし言語（英: untyped）に区分される。Smalltalk の場合、変数に対する操作は全てメッセージ送信であり、変数の種類(型)毎にできる操作は決まっていない。また、オブジェクトに対しメッセージを送った場合、そのオブジェクトがメッセージに対応するメソッドを持っていなくとも実行環境がエラーを発生させる事はない。メッセージに対応するメソッドが存在しない場合、例外を出すか無視するかは、クラスに実装されたメソッドの内容次第である。したがって Smalltalk には型付けの概念はない。例えば、Pharo の MessageCatcher は全てのメッセージを拾うため、どんなメッセージを与えられても例外が発生することはない。また、GNU Smalltalkではnilから派生したクラスのオブジェクトに存在しないメソッドに対するメッセージを送ると何も反応しない。ただし高速化のため後述の特殊セレクターを使用した場合実行時に型検査する処理系が多い。ちなみに Smalltalk は基本的に中間言語に翻訳され、翻訳時にエラーを発生させるため構文検査は静的である。
制御構文の節で述べた通り、Smalltalkの殆どの制御構文はメッセージ式である。Smalltalkに明るくないプログラマーからは言い方や見方を変えただけと捉えられがちである。Smalltalkの制御構文は実際にメッセージであるがゆえに究極には制御構文の構文要素を次のように変数に分解してしまうことが出来る。変数に分解した分岐制御の例：| then else message condition |then := [ 1 ].else := [ 2 ].message := MessageCatchernewifTrue:  thenifFalse: else.condition := 2 = 2.^ message sendTo: condition.これらの変数に分解された構文要素は、どのクラスのオブジェクトで無いといけないという制限はない。送られたメッセージを処理することさえ出来ればあらゆるオブジェクトに置き換える事が出来る。
Smalltalkでは高速化のためいくつかのメッセージを特別扱いする。これを特殊セレクター（英: special selector）という。典型的な例は#ifTrue:ifFalse:である。下記のコードはでは「ifTrue: [5] ifFalse: [6]」を評価した時にメッセージが送られる訳ではなく、バイトコードレベルでインライン展開され飛越し命令の表現に置き換えられる。このため実際にifTrue:ifFalse: という名のメソッドが呼ばれることもない。また、trueやfalse以外に上記のようなBoolean用のメッセージを送ると処理系によってはMustBeBoolean例外を発生させる。このように頻繁に使用する分岐や反復を特別扱いすることで性能低下を防いでいる。3 < 4 ifTrue: [ 5 ] ifFalse: [ 6 ].セレクターと名がつくが特殊セレクターは、特別扱いする条件が引数の状態を含んでおり、たとえ同じセレクターを使ったメッセージでも引数が条件に一致しなければ特別扱いしない。例えば下記のように引数に直接ブロックを指定していない場合では多くの処理系(VisualWorks, GNU Smalltalk等)は特別扱いせずメッセージ送信を実行する。| then else |then := [ 5 ].else := [ 6 ].true ifTrue: then ifFalse: else.特殊セレクターはあくまで高速化の手段であるため種類は処理系によって異る。どの処理系が何を特殊セレクターとして扱うかは処理系ごとに提供される説明資料に記述されている。
クラスオブジェクトもオブジェクトであるため、所属するクラスが存在している。クラスオブジェクトが所属するクラスはMetaclassというクラスのインスタンスオブジェクトである。ByteString.                   "-> ByteString"ByteString class.             "-> ByteString class"ByteString class class.       "-> Metaclass"Metaclassも当然ながらクラスに所属しており、再帰的にMetaclassに属するようになっている。' ' class.                               "-> ByteString"' ' class class.                         "-> ByteString class"' ' class class class.                   "-> Metaclass"' ' class class class class.             "-> Metaclass class"' ' class class class class class.       "-> Metaclass"' ' class class class class class class. "-> Metaclass class"クラスオブジェクトが所属するMetaclassのインスタンスオブジェクトは特殊なオブジェクトであり、クラスの継承階層と同様に継承階層を持っている。Collection  class superclass. "-> Object class"Object      class superclass. "-> ProtoObject class"ProtoObject class superclass. "-> Class"クラスオブジェクトはMetaclassから生成された単なるオブジェクトで有ることから、Smalltalkが標準で提供するクラスオブジェクトとは異なる独自の構造をもったクラスオブジェクトを作ることができる。例えば以下のようにメソッドの変わりにブロックを持つ無名クラスを作成することも出来る。| class object |"Metaclassからクラスオブジェクトを生成"class :=Class newsuperclass: Object;methodDictionary: MethodDictionary new."生成したクラスオブジェクトのセレクターにメソッドではなくブロックを紐付け"classmethodDictionaryadd:#something1: -> [ :value | value ] block;add:#something2 -> [ 2 ] block."生成したクラスオブジェクトをインスタンスオブジェクトの生成に使用"object := class new.Transcriptshow: ( object something1: 1 ) printString;nl."生成したクラスオブジェクトを基底クラスとして使用"classsubclass:#ExampleinstanceVariableNames:''classVariableNames:''poolDictionaries:''category:''.
文法の節で述べた通りSmallatalkでは定数も全てオブジェクトである。どんな定数であれ#classや#inspectといった基本的なセレクターを使ったメッセージを受け取ることが出来るため、基本的な操作であれば定数と他のオブジェクトを区別する必要はない。| showClass |showClass :=[ :object |Transcriptshow: object class name;cr.].showClassvalue: Object new; "-> Object"value: Object;     "-> Object class"value: nil;        "-> UndefinedObject"value: 0;          "-> SmallInteger"value: 0.0;        "-> Float"value: 0.0e1;      "-> Float"value: $0;         "-> Character"value: '';         "-> ByteString"value: #a;         "-> ByteSymbol"value: #'a';       "-> ByteSymbol"value: #();        "-> Array"value: [].         "-> BlockClosure"
Smalltalk は、任意の広さで確保した領域を持つ可変長オブジェクトを作ることが出来る。Smalltalkには配列を表わすためArray等が存在するが、これらのクラスオブジェクトは可変長オブジェクトを使って構築されている。可変長オブジェクトの領域は、オブジェクトの生成したときの一度だけしか広さを指定できない。また、クラスオブジェクトの登録時にvariable〜で始まるセレクターを使っている必要がある。ObjectvariableSubclass:#ExampleArrayinstanceVariableNames:''classVariableNames:''poolDictionaries:''category:'example'.| array |array := ExampleArray new: 100."要素100個分の領域を確保した可変長オブジェクトを生成する。"array at: 1 put: 0."1番目の要素に0を入れる。"array at: 1."1番目の要素を取り出す。"
ハンドルが参照している記憶領域上のテーブルを書き換えることによりSmalltalkは、あるオブジェクトを参照している全ハンドルの参照先を一気に変更することができる。ハンドルテーブルの書き換えには#become:を用いる。ただし、数字や文字列といった定数オブジェクトは置き換えることはできず、定数を置き換える際は定数を保持しているオブジェクトを置き換える必要がある。| value1 value2 |value1 := 'hello' asValue.value2 := value1. "この時点ではvalue2はValueHolder('hello')"value1 become: 'こんにちは' asValue. "この時点でvalue2はValueHolder('こんにちは')になる"#become:を使っている良い例はクラスオブジェクトの再登録である。Smalltalkではクラスオブジェクトはインスタンスオブジェクトが生きている間でも再登録可能でなければならず、インスタンスオブジェクトを生きたままクラスオブジェクトを再登録するために使われている。
弱参照は参照カウント方式を使う言語でよくライブラリーとして実装されるがSmalltalkではハンドルの制御を用いた言語機能として用意されており相互参照しているが不要になっているオブジェクトを迅速に解放するために使われている。弱参照には#makeWeakを用い、#makeWeakを受け取ったオブジェクトは弱参照となる。| holder object |holder := ValueHolder new.holder makeWeak. "holderが弱参照になる。"object := Object new.holder value: object.ObjectMemory compact. "ごみ回収。この時点ではholder valueはnilではない。" object := nil.  ObjectMemory compact. "ごみ回収。この時点でholder valueはnilとなる。"
カゲロウ(Ephemeron)は、どこからも参照されなくなった連想配列の要素を解放するために導入された記憶領域の管理機構でありSmalltalkで初めて実装された。例えば連想配列の添字として#keyがあったとして、#keyが連想配列以外の変数で参照されていなければ連想配列の要素は必要ない。このように不要となった要素を解放するために用いる。オブジェクトをカゲロウ状態にするには#makeEphemeronを用いる。| association key |key := Object new.association :=Associationkey: keyvalue: Object new.association makeEphemeron. "associationがカゲロウになる。"ObjectMemory compact. "ごみ回収。この時点ではassociation keyとassociation valueは共にnilではない。" key := nil.ObjectMemory compact. "ごみ回収。この時点ではassociation keyとassociation valueは共にnilとなる。"ここでは連想配列の要素としてよく使われるAssociationを例としているが、カゲロウが消滅する基準は最初のインスタンス変数でクラスに依存しないためどんなクラスでもカゲロウにすることができる。
セレクターを表す識別子については、基本的に1文字目に小文字を使うが、メソッドが存在するセレクターを避けたい場合は大文字を使う事が慣習になっている。GNU SmalltakやVisualWorksで用意されている名前空間は、大文字のセレクターを使う典型的な例である。Smalltalk SystemExceptions InvalidValue signalOn: 0. "「Smalltalk」以外は全てセレクター"なお、名前空間が使える環境の多くは、翻訳時に名前空間の名前解決できる「.」区切りの拡張構文が用意されており、実際にはこちらの構文が使われることが多いため、セレクターを使った名前空間の指定を見る機会は少ない。
オブジェクトの生成には #new セレクターを使ったメッセージを使う。他の言語と違い、new は演算子ではない。|object|object := Example new. "Exampleクラスオブジェクトに「new」メッセージを送りオブジェクトを生成。"Smalltalk ではクラスオブジェクトのメソッドもインスタンスオブジェクトのメソッドと同様に派生クラスによる再定義が可能である。このため new メソッドを再定義し初期化処理を記載する事が出来る。new メソッドを再定義してしまうとオブジェクトの生成自体が不可能になるように思われるが、本来 new メソッドは #basicNew セレクターを使ったメッセージをBehavior に送ってオブジェクトを生成しているためオブジェクトの生成手段がなくなるわけではない。このため new メソッドを再定義しても 「basicNew」メッセージをBehaviorに送ることでインスタンスオブジェクト生成することが出来る。ただし、実際の初期化に new メソッドが使われる事は多くない。実際には慣習としてクラスの作者が新たに登録したインスタンス・クリエイションと呼ばれる new とは別の初期化用メソッドが使用される。インスタンス・クリエイションは一般的なクラスオブジェクトのメソッドであり、そのメソッドの内部で 「new」メッセージやその他のインスタンス・クリエイションを使って初期化済みのオブジェクトを生成する役割を持っているだけで基本的にその他のメソッドと変わらない。一般的にinstance creationというプロトコルに登録される。| number |number := Number readFrom: '10'. "readFrom:がインスタンス・クリエイション".Smalltalk では1個のセレクターに対し1個のオブジェクトから複数のメソッドを関連付けられないため 「new」メッセージの送信によりできる初期化は1個のオブジェクトにつき一通りの初期化だけである。このため複数のインスタンス・クリエイションを用意することで用途に応じた複数の初期化方法を提供しているのである。インスタンス・クリエイションは一般的なメソッドのひとつでしかない。このためインスタンス・クリエイション持つクラスオブジェクトはアブストラクト・ファクトリーとして機能する。具体的には次のように使われる。defaultDatabase"既定のデータベースのクラスオブジェクトを定義した派生クラスで再定義可能なメソッド。 オーバーライドされた際は、必ずしもクラスオブジェクトが返されるとは限らず、インスタンス オブジェクトが返される場合もある。"^ PostgreSQL.database"databaseへの接続を返すメソッド。 defaultDatabaseにより返されたPostgreSQLに対し、インスタンス・クリエイションである #connect:セレクターを使ったメッセージが送られ、PostgreSQLのインスタンスオブジェクトが生成される。 ただし、defaultDatabaseは、派生クラスによって再定義できるため、#connect:セレクターを使ったメッセージが 必ずしもPostgreSQLクラスオブジェクトに送られるとは限らない。"^ self defaultDatabase connect: self configuration.また、Smalltalk はクラスメソッドを上書きできるため、インスタンス・クリエイションを次の様に実装する事で基本的な初期化処理を派生元のクラスに任せることができる。x: aX y: aY^ self newx: aX;y: aY.上記は、2次元座標用のクラスオブジェクトのインスタンスオブジェクトを初期化する派生元のクラスオブジェクトに実装されたインスタンス・クリエイションである。このクラスオブジェクトを継承した2次元座標用のクラスオブジェクトでは#x:y:セレクターを使ったメッセージに対応するメソッドを実装する必要はない。インスタンス・クリエイションを利用したパターンは Smalltalk では広く利用され、いたる所で見ることが出来る。