TOP

OKLab

Smalltalk入門

目次

はじめに

目次へ戻る

動作環境

目次へ戻る

対象者

目次へ戻る

Smalltalkとは?

目次へ戻る

環境構築

目次へ戻る

tar -zxvf smalltalk-2.1.8 # cd smalltalk-2.1.8 # ./configure --disable-gtk # make # make install


今回は、コンパイル時にエラーがgtkがらみで発生したので--disable-gtkというオプションをつけてコンパイルを通しました。


目次へ戻る

最終目的

Smalltalk版2c(バイナリクロック)の作成をします。オブジェクト指向の源流を学びます。

 

目次へ戻る

環境設定

GNU Smalltalkはimage pathとkernel pathを環境変数で定義できます。

環境変数SMALLTALK_IMAGEが定義されていないと、デフォルトでは/usr/local/share/gnu-smalltalkを確認します。

環境変数SMALLTALK_KERNELが定義されていないと、デフォルトでは/usr/local/share/gnu-smalltalk/kernelを確認します。

[s-okita@localhost s-okita]$ gst -v
GNU Smalltalk version 2.1.8
Copyright 2003 Free Software Foundation, Inc.
Written by Steve Byrne (sbb@gnu.org) and Paolo Bonzini (bonzini@gnu.org)

GNU Smalltalk comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Smalltalk under the terms of the
GNU General Public License.  For more information, see the file named
COPYING.

Using default kernel path: /usr/local/share/smalltalk/kernel
Using default image path: /usr/local/share/smalltalk

 

目次へ戻る

コメント

 

目次へ戻る

コーディング規約

 

目次へ戻る

基本構造

 

目次へ戻る

ハローワールド

[s-okita@localhost s-okita]$ gst GNU Smalltalk ready

st> 'hello world' printNl ! 'hello world' 'hello world' st>

GNU Smalltalkをインストールするとgstコマンドが使えるので、実行するとst>というプロンプトが表示されます。上記コマンドを入力するとHELLOWORLDが表示されます。このst>プロンプトは^D(control-D)で終了できます。

gstコマンドに-qオプションをつけると、print実行情報が表示されなくなるので1行のみ'hello world'と表示されます。

この例では、Stringオブジェクトの'hello world'を作成し、printNlというというメッセージでオブジェクトに送信( ! )しています。

 

インタプリタモードではなく、ファイルにSmalltalkのソースコードを記述しても実行できます。

[s-okita@localhost st]$ cat hello_Smalltalk.st
'hello world' printNl !
[s-okita@localhost st]$ gst hello_Smalltalk.st
'hello world'

 

目次へ戻る

データ形式

SmalltalkがJavaやC++と決定的に違うのは、インタプリタ言語であるということです。Perlなどのインタプリタ言語が型を意識せずに演算等が可能なようにこの言語もある程度型を意識せずに作成できます。これは、実行時に動的に処理するためには非常に強力な機能です。しかしパフォーマンスがコンパイラ言語や静的に型を持つ言語より劣るという諸刃の剣でもあります。

現在、型を意識せずに且つある程度のパフォーマンスを発揮できる言語としては、Objective-Cなどがあげられます。

今後のサンプルでは、Java, C/C++などに対して、型が存在していないことを意識して取り組んでみてください。

 

目次へ戻る

演算子

 

[s-okita@localhost s-okita]$ gst
GNU Smalltalk ready

st> ( ( 5 + 5 ) * 2 ) + ( 9 / 3 ) printNl !
3
23

 

目次へ戻る

配列

Smalltalkでは、代入の演算子に=ではなく:=を使います。(Oracle PL/SQLも同様に:=を使ってました)

st> [s-okita@localhost s-okita]$ gst
GNU Smalltalk ready

オブジェクトをインタプリタ上で保持するための領域確保します
st> Smalltalk at: #x put: 0 !
0


変数xに配列を割り当てます
st> x := Array new: 20 !
Array new: 20 "<0x42174178>"

一番目のデータを表示しようとしているが何もないのでnilが表示されます
st> (x at: 1) printNl !
nil
nil

一番目にデータを格納します
st> x at: 1 put: 99 !
99

もう一度取り出してみます
st> (x at: 1) printNl !
99
99

 

目次へ戻る

I/O

 

目次へ戻る

制御構造

分岐

他の言語とは非常に異なった書き方をします。

[s-okita@localhost st]$ cat if.st
Object subclass: #ConditionTest
        instanceVariableNames:
                'count age name'
        classVariableNames: ''
        poolDictionaries: ''
        category: nil
!
!ConditionTest class methodsFor: ''!
new
        |r|
        r := super new.
        r init.
        ^r
!!
!ConditionTest methodsFor: 'ini'!
init
        count := 10.
        age   := 30.
        name  := 'helloman'.
!!
!ConditionTest methodsFor: ' if test '!
checkTest
        count := count + 1.
!!
!ConditionTest methodsFor: 'print'!
printOn: stream
        ( count == 10 )
                ifTrue: [ 'count is 10' printNl ].
        ( age  ==  29 )
                ifFalse: [ age printNl ].
        ( name == 'helloman' )
                ifTrue: [ 'count is 10' printNl ].
!!

Smalltalk at: #a put: (ConditionTest new)!
a printNl!
[s-okita@localhost st]$ gst if.st
'count is 10'
30

反復

[s-okita@localhost st]$ cat loop.st
Object subclass: #LoopTest
        instanceVariableNames: 'count'
        classVariableNames: ''
        poolDictionaries: ''
        category: nil
!!
!LoopTest class methodsFor: ''!
new
        |this|
        this := super new.
        this init.
        ^this
!!

!LoopTest methodsFor: ''!
init
        count := 0.
!!
!LoopTest methodsFor: ''!
counter
        count printNl.
        1 to: 5 do:
                [:x |
                        count := count + x.
                        count printNl.
                ]
!!

[ LoopTest printNl ] !
[ LoopTest counter ] !

Smalltalk at: #id put: (LoopTest new)!
id counter!
[s-okita@localhost st]$ gst loop.st
0
1
3
6
10
15
目次へ戻る

API

 

目次へ戻る

クラス

[s-okita@localhost objc]$ gst
GNU Smalltalk ready


スナップショットの保存
st> ObjectMemory snapshot: 'class_sample.im' !
"Global garbage collection... done"
ObjectMemory

アカウントクラスの作成
st> Object subclass: #Account
st> instanceVariableNames: 'balance'
st> classVariableNames: ''
st> poolDictionaries: ''
st> category: nil !
Account

comment:でコメントをつけられます。
st> Account comment: 'Account class inheritance Object Class.' !Account

コメントの表示
st> (Account comment) printNl !'Account class inheritance Object Class.''Account class inheritance Object Class.'


Stringクラス、Integerクラス、Objectクラス、Classクラスのコメントを表示してみます。
既存のクラスのコメントを確認することで概要がわかります。Java/C++にはない機能です。
st> (String comment) printNl !'My instances represent ASCII string data types.  Being a very commoncase, they are particularly optimized.''My instances represent ASCII string data types.  Being a very commoncase, they are particularly optimized.'
st> (Object  comment) printNl !'I am the root of the Smalltalk class system.All classes in the system are subclasses of me.''I am the root of the Smalltalk class system.All classes in the system are subclasses of me.'
st> (Class comment) printNl !'I am THE class object.  My instances are the classes of the system.I provide information commonly attributed to classes: namely, theclass name, class comment (you wouldn''t be reading this if itweren''t for me), a list of the instance variables of the class, andthe class category.''I am THE class object.  My instances are the classes of the system.I provide information commonly attributed to classes: namely, theclass name, class comment (you wouldn't be reading this if itweren't for me), a list of the instance variables of the class, andthe class category.'
目次へ戻る

クラスの初期化と開放

インスタンス生成用のメソッドを作成します。Javaでいうコンストラクタです。

 

st> !Account class methodsFor: 'instance creation' !Account class

newメッセージの動作を定義します。!!で終了です。問題がなければ何も表示されません。問題があるとエラーメッセージが表示されます。st> newst> |r|           ローカル変数rの定義st> r := super new.         Objectクラスを初期化(new)してr変数に格納st> r init.              Accountクラスのinitメソッド呼び出しst> ^r            return what r is attached to.st> !!

インスタンス化してみます。
st> Account new !Object: Account new "<0x42167d50>" error: did not understand #initAccount(Object)>>#doesNotUnderstand:Account class>>#newUndefinedObject>>#executeStatementsnil

initメソッドがAccountクラスにないためエラーになります。そこでinitメソッドを作成します。
st> !Account methodsFor: 'instance initialization'!Accountst> initst>  balance := 0st> !!

再度、インスタンス化します。今回は正常にインスタンス化できました。
st> Account new !Account new "<0x42169528>"

メモリを確保します。
st> ObjectMemory snapshot: 'class_test.im' !"Global garbage collection... done"ObjectMemory

Smalltak a変数にAccountオブジェクトを格納します。st> Smalltalk at: #a put: (Account new) !Account new "<0x421403f8>"

a変数をprintNlメソッドで確認してみます。'an Account'と表示されAccountオブジェクトが参照されていることがわかります

st> a printNl !an AccountAccount new "<0x421403f8>"
目次へ戻る

インスタンス変数・インスタンスメソッド

目次へ戻る

クラス変数・クラスメソッド

  • instanceVariableNames:を利用してインスタンス変数を作成します。Smalltalkは型を必要としません。
  • methodFor:を利用してインスタンスメソッドを作成します。
  • classVariableNames:を利用してクラス変数を作成します。
  • class methodFor:を利用してクラスメソッドを作成します。



[s-okita@localhost st]$ cat instance_method.st
ObjectMemory snapshot: 'instance_method.im' !
Object subclass: #Human
        instanceVariableNames:
                'age'
        classVariableNames:
                'think'
        poolDictionaries: ''
        category: nil
!
Human comment: 'Pearent(Base) Class' !

!Human class methodsFor: 'instance creation' !
new
        |r|
        r := super new.
        r init.
        ^r
!!

!Human methodsFor: 'initializer' !
init
 age := 0.
!!

!Human methodsFor: 'old'!
addAge: val1
        age := age + val1
!!


!Human methodsFor: 'view'!
printOn: stream
        age printOn: stream.
!!



Smalltalk at: #a put: (Human new) !

a addAge: 25!
a printNl !
[s-okita@localhost st]$ gst instance_method.st
"Global garbage collection... done"
25
目次へ戻る

アクセス制御( Access Privilege )

 

目次へ戻る

継承(Inheritance)

[s-okita@localhost st]$ cat instance_method.st
ObjectMemory snapshot: 'instance_method.im' !
Object subclass: #Human
        instanceVariableNames:
                'age'
        classVariableNames:
                'think'
        poolDictionaries: ''
        category: nil
!
Human comment: 'Pearent(Base) Class' !

!Human class methodsFor: 'instance creation' !
new
        |r|
        r := super new.
        r init.
        ^r
!!

!Human methodsFor: 'initializer' !
init
 age := 0.
!!

!Human methodsFor: 'old'!
addAge: val1
        age := age + val1
!!

!Human methodsFor: 'view'!
printOn: stream
        age printOn: stream.
!!



Smalltalk at: #a put: (Human new) !

a addAge: 25!
a printNl !

Human subclass: #Japanese
        instanceVariableNames: 'grace'
        classVariableNames: ''
        poolDictionaries: ''
        category: nil
!
Japanese comment: 'Japanese has graceful hearts.' !

!Japanese methodsFor: 'initializer'!
init
        grace := true.
        ^super init
!!
!Japanese methodsFor: 'instance method definition'!
printOn: stream
        grace printOn: stream
!!


Smalltalk at: #b put: (Japanese new) !
b printNl!
[s-okita@localhost st]$ gst -q instance_method.st
"Global garbage collection... done"
25
true

 

目次へ戻る

ポリモーフィズム(Polymorphism)

 

目次へ戻る

クラスオブジェクト

 

目次へ戻る

オーバーライド(Override)

 

目次へ戻る

オーバーロード(Overload)

 

目次へ戻る

インタフェース

 

目次へ戻る

セレクタ

 

目次へ戻る

カテゴリ

 

目次へ戻る

その他

snapshot(現状の保存)の方法。 GNU Smalltalk User's Guideでは、Smalltalk snapshot:となっているがドキュメントが古いようです。

[s-okita@localhost s-okita]$ gst
GNU Smalltalk ready

st> ObjectMemory snapshot: 'test_hoge.im' !
"Global garbage collection... done"
ObjectMemory
目次へ戻る

デバック

 

目次へ戻る

最後に

 

目次へ戻る

参考資料

GNU Smalltalk User's Guide

目次へ戻る


イバラキングへのリンク Get Firefox Valid XHTML 1.1 Apple Darwinへのリンク