歴史的には、オブジェクト指向言語の源流は、Simula。それらを参考にEiffelやSmalltalkが
作られ、C++やらなんやらが作られはった。

オブジェクト指向の能書きは、シミュレーションの際に扱うデータの抽象化にあるんや。
たとえばやなあ、ウインドウを抽象的に扱う場合、座標をx,yと個々に変数を扱うより、
ウインドウちうオブジェクトのx,yちう抽象データ型があったほうが取り扱いやすいちうわけや。
プログラム中、変数を無数に無作為に定義するよりも、座標やベクトルちう構造を持って
いたほうが理解しやすいやろ。

例えば、

dim x1 as integer
dim y1 as integer
...

という変数が、無数にあるよりも、

type axis
	x1 as integer
	y1 as integer
end type

という構造体の変数型を使って、

dim point1 as axis
dim button as axis

ちうような扱い方のほうが理解しやすいちうわけや。変数名が無数にあったら可読性にも難があるんや。
数学のスカラ変数とベクトルのように、現実の計算をする場合、スカラ変数を複数利用する
よりも、あるまとまった数値としたほうが都合がええわけや。
二次元ベクトルを考えるとき、既存のBASIC言語には備わっておらへん変数型やけど、

type vector
	x as double
	y as double
end type

なんやらとするやろ、"ワイ(俺)"変数型が作れるちゅうワケや。このようなtype/end typeを使う変数定義は
構造体と呼ぶ。
使うときは、

dim p1 as vector
p1.x=100
p1.y=120

等とする。

これらと同じ発想で、関数やメソッドについても同じレベルで扱えるとうれしおます。
構造体に関数やプロシージャを含めるゆう事。
大体において、そういった独自の変数型には、その型に対応するメソッドや関数が必要やからや。

ここでクラスちう能書きやステートメントが登場するちうわけや。クラスは日常用語のクラスやのうて
数学の世界の用語、階級とかランクとかいう意味や。
例あげたろか、たとえばやなあ構造体から進歩してクラスをabで使うと、

class c_test
	public
		var1 as integer

		sub hello()
			print "hello"
		end sub

		sub show()
			print var1
		end sub
end class

dim a as c_test

a.var1=123
a.show()
a.hello()

等とするちうわけや。構造体とメソッドが一体化したクラスと呼ばれるもんとなるちうわけや。クラス内の変数var1
は構造体のように参照できて、関数やプロシージャもクラスとつよ結びついとる。

実際に使う際には、aちう変数はc_test型の変数ちう意味になり、
クラス内の各要素は"."ドット記号を使うてアクセスするちうわけや。こら構造体と同じや。
せやけど、構造体とちゃうんは、変数と関数/プロシージャもドットでアクセスできること。

オブジェクト指向言語では、
a.var1のようなクラス内にある変数を、メンバーとかプロパティちう。
クラス内の関数やプロシージャを、メソッドちう。

クラスが初期化されたときにじぇったい呼ばれるメソッドもあるちゅうワケや。また消去されるとき
にじぇったい
呼ばれるメソッドもあるちゅうワケやそれらをコンストラクタ、デストラクタとよぶ。


ここまでの例は、クラスをつこうただけ。オブジェクトは関係してへん。
クラスだけでも色々なことが出来よるが、
今度はクラスに基づいてコンピュータ上にオブジェクトを作成してみるちうわけや。

class ctest
	public
		ary[100] as integer

		sub clear()
			dim i as integer
			for i=0 to 99
				ary(i)=0
			next i
		end sub
end class

dim obj as *ctest
obj=new ctest()

obj->ary(10)=123
obj->clear()

print obj->ary(10)

delete obj

debug

ここではクラスとしてctest型を定義してん。定義は前と同じ。ちゃう所は、dim文以降。
dim文(dim obj as *ctest)でクラスctestの型のポインタをobjとして作り、new演算子で
コンピュータ内のメモリーにctest型のオブジェクトを動的に作成するちうわけや。
objは、そのオブジェクトの位置を示すアドレスが保存されるちうわけや。newされて動的にメモリが
確保されたオブジェクトを指し示してん。

こないな作ったオブジェクトは参照時にはアロー演算子"->"を使うわ。単にクラスに定義
されとったもんを参照する場合は、"."演算子でよかったがここではちゃう。
newしてクラスからオブジェクトを作る場合はアロー演算子を使うと覚えておきまひょ。

さらにオブジェクトはnewで作ったら、消さなあかん。作ったもんの責任で。
それがdelete objで、deleteされて始めてコンピュータ上から消えるちうわけや。

こうしてnewで動的に作成したオブジェクトは、インスタンス(実体)とも呼ぶ。

ここで作ったオブジェクトは配列機能を持つもんやけど、単に変数を配列として作るより
進化してん。
なんでやったら、配列データと手続き(clear)が一緒になってて一つのクラスとして定義されとる。
今回はclearちうプロシージャだけやけど、配列操作に便利ええ関数が他にもあれば便器...おっとちゃうわ、便利や。
newしてクラスからオブジェクトを作る行為は、動的にメモリを確保するmallocに近いとも
言えるちうわけや。

単にクラスを使う場合と、動的にクラスからオブジェクトを作る方法があんねんと覚えて
おきまひょ。こら用途によって区別するちうわけや。


クラスについてもう少し考えてみよう。
例えば、整数型というクラスCIntがあったとして、

CInt.Maxsize
CInt.to_double
CInt.to_strings

Dim obj As CInt(100)

print obj.Maxsize
print obj.to_double

やらなんやらちうメンバーがあったら興味深いちうわけや。なんでやったら概念として、整数ちうクラスがあって、
それらのオブジェクトは、どないな整数値であっても最大値を知っとるし、文字列変換の
関数を知ってて、実数に変換する手段も知っとる。
機能は関数ライブラリではなく、整数ちうクラスが知っとるべきや、ちう訳や。

今までやと、変数ちう値と、手続きは別やった。文字列や実数への変換は、BASICの
標準関数から探す必要があるんや。こら抽象的に物事を扱いたいときにはひどく見通しが悪う
便利わるい。
アニメキャラクタの服を変えると言うたとき、obj.change()と書いたほうが現実をより上手く
プログラム上で現してん。

ウインドウズやらなんやらのOSの例でも同じや。
CWindowちうクラスがあって、ウインドウを表示したり座標を知りたい場合、

obj.show()
position=obj.x

ちう書き方のほうが、便利や。いちいち別関数のwin_show(obj)やなんて書いとる必要はあらへん。
さらに、CWindowちうクラスによって、単なる数列の塊が、ウインドウちう存在に
きわめて近い扱いを、プログラミング言語上で行えることに注目してほしおます。

もし、abにBASICのクラスがあれば、標準関数やのうてクラスを使えるちうわけや。
CInt,CDouble,CStringやらなんやらのクラスがあれば、使う側はBASICライブラリやのうて
クラスを使えるちうわけや。そのとき、文字列は、

Dim str As CString("hello")
str.length()
....イコール...
"hello".length()

とするやろ、ほしたら文字列自体がオブジェクトやから、自身の文字列の長さをオブジェクトが
答える事ができるようになるちうわけや。

  • 継承

さらに、クラス間にはやや共通した側面があることにも気づく人もおるやろ。
例あげたろか、たとえばやなあ、コンピュータのウインドウやボタンやエディットボックスはみな画面に表示される
が、座標系ちう共通した値を保持してん。
数値ちう能書きには、四則演算が共通してて、似とる。数の分類をクラスで表現できるんとちゃうか、ちうアイデアが生じるちうわけや。

CNumber ----> CInteger ---> CIntArrayList
         +--> CLong
         +--> CDouble ----> CComplex
         +--> CVector

こないなふうに、数とゆうグループがあって、整数/実数のほか、それらのええトコを含むベクトル
とか複素数なんてグループ化が出来るちゅうワケや
時計の例なんてものも考えることが出来るちゅうワケや

CObject ---> CClock -----> CDigitalClock
                      +--> CAnalogClock

まるで進化の過程のようやけど、これらのグループ分けもクラスで可能で、それらを継承とか
クラスの継承ちう。

ここでは、CNumberがクラスのホンマの基本機能しかいないちうわけや。これをスーパークラスちう。
子クラスはスーパークラスに機能を追加して作成されたもんや。
オブジェクト指向のクラスは、こうして機能の継承関係を使うて、重複した機能を実装する
必要なく、全体をどエライ上手くライブラリとして実装し、表現するっちうことができるちうわけや。
使う側も、CClockの基本メソッドを知っていれば、デジタルもアナログもクラスとしては
まるっきし同じインターフェースで利用できる事になるちうわけや。

これらの図で示した継承ちう機能のツリーを継承ツリーと呼ぶ。
これらの継承図をダイアグラムで表現する方法は幾つも提案されており、Microsoftの
エクセルやVC++をこーたら貰えた緑色のクラス図のポスターや、UMLやらなんやらが有名なんや。
他にも幾つもあるんや。自作するっちうことも可能や。

実際にabのクラスで継承を使うには、

class CSuper
	public
		var1 as integer
	sub test()
	end sub
end class

class CMyObj
	inherits CSuper
	public
		var2 as integer
	sub mymethod()
	end sub
end class

とする。ここではCSuperがスーパークラスで、それを継承してCMyObjが作られておるちゅうワケや

CSuper ---> CMyObj

とゆう継承関係だちゅうワケや。

inheritsという箇所で、継承元のクラスを指定する。
このCMyObjはCSuperを継承しているので、当然CSuperとCMyObjの両方のメンバが利用できる。
つまり、

dim obj as CMyObj

obj.var1=10
obj.test()
obj.mymethod()

が可能ちう訳や。逆にCSuperでは、var2やらなんやらのメンバーは無いので使うことはでけへん。
この関係を上手く利用してクラスを作ると、どエライ判りやすいちうわけや。

CSuperには仮想関数(VirtualFunction)ちうメソッドも定義できるちうわけや。こらスーパークラス
であらかじめ定義しておき、継承後にメソッドを書き換えることが出来よる特別なメソッドや。
例あげたろか、たとえばやなあ、CClockで定義したメソッドのうち、CAnalogClock/CDigitalClockで異なる実装が
必要な場合、継承後、クラスの仮想関数を書き換えるちうわけや。
そうするっちうことで、クラスの継承を利用し、クラスの多様性を確保してん。
仮想関数ゆうものがあることも覚えておきまひょ。

クラスには継承ちう親子関係が存在し、それを利用するっちうことで、データ構造を
あんじょう扱うことが出来よる。

こうして作成されたクラス群をクラスライブラリちう。使う側はクラスライブラリを
利用するだけで高機能なプログラミングが可能や。
あらかじめ目的によってクラスが用意されていれば使う側は楽でええ。
上に示したCNumberクラスも、クラスライブラリちう。

  • クラス設計

ここまでくると、プログラミングの作業は、クラスライブラリの設計如何にかかっとるというても
過言ではない。なんでやったら、クラスライブラリの設計は目的や現実のもん毎に基づいて設計されるため、
じぇったい、この設計段階が重要になるさかいや。
従来型のプログラミングと比較して、オブジェクト指向言語ではクラスライブラリの設計が大きな鍵を
握ることになる。

また、クラスライブラリを使うプログラミングの場合、利用者は頻繁に継承をつかうことは
避ける必要があるんや。
なんでやったら、本来、継承はクラスライブラリの設計が関係してん問題で、
プログラム段階で特別クラスが必要となる以外、頻繁に継承をする必要はあらへんからや。
混乱の元となる可能性も高なる。

オブジェクト指向の本に、りんごは赤く、丸いもん云々ちう説明があるんは、現実の世界の
特徴や側面に注目して、現実の物体をオブジェクトとして表現する際に、何に注目する必要が
あるんかをぬかしておる。

ようけのオブジェクト指向プログラミング言語は、言語レベルでごっつう巨大なクラスライブラリ
が作られとる。使う側はそれらを組み合わしたらよいちうわけや。
ab4ではクラスライブラリは存在せんが、自作プログラムの為にクラスライブラリを作る場合は、
目的に基づいてじぇったいクラスの設計をする必要があるんや。



  • コンポジション

今までクラスは継承ちう関係があり、それを利用して機能を持たせることが可能と書いたわけや。
この継承ちう関係は、クラスの親子関係が存在する場合に当てはまるもんや。
たとえばやなあ、アナログ時計ちうクラスを作った場合、時計ちう上位のクラスから継承するっちうことになるちうわけや。
これを言葉で言い表したら、”アナログ時計”は”時計”ですね、ちう文脈がなりたつ。
要は、継承ちう機能が使えるんは、こないな言葉で表現できる範囲のなかにあるクラスの関係であるちうことや。

CObject -> CClock -> CAnalogClock
                  +> CDigitalClock

この例では、CAnalogClockはClockの仲間として分類できるさかい、こないな関係でクラスを継承ちう機能を
使うてまとめることが出来よる。

これに対して、べつの考え方があるんや。たとえばやなあ、

class CMyClock
 public
   sub setTime()
	dim obj as CDigitalClock()
	obj.time("00:00:00")
   end sub
end class

dim clockobj as CMyClock

やらなんやらのクラスがあったとする。このクラスはわし(俺)クラスでオノレで作ったもんやけど、
こら継承を使わんといて、単に親クラスとなるCDigitalClockのクラスをsetTime()メソッド内で使うておる。
機能としては継承を使うておらへんが、まるっきし別のクラスちう訳とちゃうんや。なんでやったらメソッドsetTime()内部
で、CDigitalClockクラスを使うておるからや。こら継承と似た機能と考えられはる。


CObject -> CClock -> CAnalogClock
                  +> CDigitalClock
                   +=====> CMyClock


こないな考え方も出来よるちうわけや。

こないな関係をコンポジションちう。こら継承を使わんといて、他のクラスを継承を使わず代替する方法の一つで、
言葉で言い表すと、"マイ時計クラス"は"時計"を持ちまんねん、ちう文脈になるちうわけや。継承せん代わりにクラス内で
インスタンスやクラスを利用して、継承と似たような機能を実現できる訳や。こないな方法やと継承を
利用せんので,クラスライブラリの設計には影響せんが、逆に一見して記述から親クラスと強い継承関係にある
ことがまるっきし判らんゆうデメリットもあるんや。

こないな違いを区別して使うには、一つの判断方法として、言葉の文脈が当てはまるか否かで判断する、ちう
考えかたもあるんや。クラスAをスーパークラス、クラスBを子クラスとして考えると、

クラスBは、クラスAの仲間です。又は、仲間ですか?

クラスBは、クラスAを含みます。又は、クラスAを使うだけですか?

ちう文脈が成り立つ。
上に当てはまるんやったら、継承を使えるし、後者やったらコンポジションが使えるちうわけや。
そないにしてクラスライブラリの設計やらなんやらを行うわ。



  • デリゲード

デリゲードは日本語では委譲ちう。あんまりどシロウトレベルでは扱いまへん話やけど、そういった能書きがある
ちう事だけ覚えておきまひょ。

簡単にデリゲードを考える事はそれほど難しない。たとえばやなあ,これまでクラスについてさまざまに考えてきたが、
このクラスは簡単に、もう一つの表現で言うたら、クラスは変数型ともいえるちうわけや。

変数型にはいくつもん型があるが、もしポインタやらなんやらの考え方が可能やったら、
VoidPtr型が存在するっちうことに気づくやろ。実際、abにはVoidPtrちう型があるんや。
ポインタやポインタのキャストになれた人やったら、例あげたろか、たとえばやなあ、Long型の変数を、VoidPtrで扱う事が、
それほどむつかしことではおまへん、ちう点に気づいとる。
実際、abのいくつもん変数型は、VoidPtrで指し示す事が出来よる。


これと同じ考えをクラスでも行えるちうわけや。
たとえばやなあ、CClockちうクラスは、実はVoidClassみたいな型で扱え、CClockちう型で、CAnalogClockや
CDigitalClockのクラスやオブジェクトを扱えることになるちうわけや。
CAnalogClockはCClockの子やから、共通してんCClockの型としてのポインタでCDigitalClockが参照できても
おかしくはあらへん。

これのメリットは、要は、クラスのキャストを使うて、まるっきし別のクラスのメソッドを呼び出せる(参照可能)
ちう点にあるんや。
これが、委譲と呼ぶ意味や。

ちーとばかしええ加減やけど、

dim obj as *CClock()
obj=new CDigitalClock()

のようなことをして、型のキャストを使うて、別のCAnalogClock()のメソッドに、任せてしまおうゆう方法や。
(abでこないな風なことを出来よるか不明やけど)

実は、javaのインターフェースやab5のインターフェース文は、まさにこのデリゲード,委譲ちう方法を実現する
一つのメカニズムで、インターフェースちうキテレツなクラスに似たような機能を持ち、型として扱われることで、
クラスをキャストしてVoidPtrのような型として考え、他のクラスのメソッドを間接的に使うわ。それらの別クラス
実装に任せる事が出来よる訳や。
インターフェースちう構文は、そないな型のキャストのためにあるというてもええ。

ab4ではクラスのポインタのキャストが出来れあほのうやろし、ab5ではそもそも新しい機能としてインターフェースが
備わっとる。
クラスにはデリゲードちう考え方もあんねんと覚えておきまひょ。




  • オブジェクト指向の概念

ここまで、クラスとオブジェクトの関係がわかったトコロで、本来のオブジェクト指向言語
での能書きとの違いを理解しておく必要がある。

abのオブジェクト指向言語としての実装は、C++を参考に作られててクラスベースと
なっとる。コンパイラとスクリプト言語等のインタプリタでは構造も異なるので
それらの違いもあるんや。
オブジェクト指向の能書きはホンマはちごてて、
C++のオブジェクト指向が一つの方言であることを理解しておく必要があるんや。

本来、オブジェクト指向とは、さまざまなデータをカプセル化するっちうことによるメリットを
強調してん。
個々の変数を扱うよりも、クラスとほんで生成されたオブジェクトに備わった
インターフェース機能を介す事で、中身を知ることなく、オブジェクトを使うわ。
そのほうが、楽なこともあるんや。
オブジェクト指向はカプセル化や隠蔽ちう手段としたかて利用できるゆうことや。
ユーザーは細かいソースコードまで目を配ることはあらへん訳や。

カプセル化のイメージは、データと手続きが一つのセルとして組み込まれた独立した単位
として捕らえる事が出来よる。
セルの中身には変数が保存されてて、わてたちが使う場合、変数を参照したり、セルに
含まれる関数を実行したりするちうわけや。セルは抽象的な丸い物体のようなもんと考えるちうわけや。

そこで、考え方を変える必要がある。
オブジェクト指向言語では、四則演算子の記号は、従来の言語と違って
それはメソッドである。

1+1

これは式や。手続き型プログラミング言語では式として扱うわ。せやけどオブジェクト指向ではちゃう。

この式は、オブジェクト指向の世界では、1ちう数値オブジェクトが、+ちうメソッドを介して
1を扱っとる、と解釈するちうわけや。
こら従来型のプログラミング言語しかつこうたことのあらへん人にはどエライ大きな飛躍や。
メソッドにアクセスする演算子"."をわざと使うて表現したら、

1+1
1.+ 1
1.add 1
1.add(1)

という事になる。これら意味はすべて等しい。


しかも、この処理は、1ちう式を扱っとるのやなく、メッセージ(文句)として扱っとる。
ゴチャゴチャゆうとる場合やあれへん、要は、1ちうオブジェクトに、メッセージ(文句)を与えとる、と解釈されるちうわけや。

オブジェクトと、オブジェクトの間を、文句を伝え合って処理をする、ちう概念が
本来のオブジェクト指向言語の基本の考えや。
こないなモデルをアクターモデルちう。
単に関数を呼ぶとか、実行する、事やのうて、オブジェクトは独立したもんで、それに
メッセージを送ったり、受けたりする、といったほうが振る舞いとしてええ。

もしスレッドを知っていれば、オブジェクトがスレッドで実行されとったら、
コンピュータ内にはどエライようけのオブジェクトが動き、メッセージを処理してん
と理解するっちうことも可能やろ。

こないな概念が本来のオブジェクト指向の持つ意味や。

obj.i=123
obj.clear()

ちう式は、本来は、オブジェクトobjのメンバーiに123ちう値をメッセージ(文句)として渡し、
obj.clear()で、オブジェクトにメッセージ(文句)を出してん事と等しおます。
やから、言語によってはレシーバ等と表現する事もあるんや。

abのオブジェクト指向は、C++を参考にしとりC++にどエライ近いちうわけや。せやけどダンさん、従来型の記述が可能
やから、クラスのメソッドや関数について、それらをメッセージ(文句)として明示的に扱うことがあらへん。
本来はメッセージとして理解するんがホンマやと覚えておきまひょ。

ほんで、オブジェクト間の相互関係にも法則性があり、それらはコンピュータアルゴリスム
のように一定のパターンが見出せるちうわけや。それがデザインパターンなんやし、
デザインパターンとは、オブジェクト間のやりとりの基本構成や機能をまとめた、アルゴリズム
のパターン集のようなもんや。



  • 歴史

元々、オブジェクト指向言語の歴史や発想はちーとばかし変わっとる。
アランケイちう人が、コンピュータの研究をするプロジェクトの過程において、simulaちう言語を使うていてそれらの経験が
あった訳やけど、同時代の数学教育研究者の実験的プロジェクトにヒントを得ることになりよった。

それが、ロゴちう言語を作った人やったが、そのロゴちう言語は元々はロボットを使うてボウズ(子供)にプログラミング
の要素を教える事を考えとった。
ロボットに命令を与えると、紙の上でモーターで動いて、ペンを操作して絵を書く。ロボットの中心でペンが上下するちうわけや。
この機能で紙の上に絵を書く事が出来よる。これがタートルグラフィックと呼ぶ機能の原点や。

今現在のプログラミング言語にもタートルグラフィックが可能な環境もあるが、まるっきし面白ない。なんでやったら、
ロゴちう言語は、ホンマはロボットを動かす為の言語やから、画面上で動いて絵を書く事が出来ても
ハードウエアとしてのロボットがまるでシカトされとるさかい、まるっきし意味があらへん。
ロボット操作言語で教育する、ちう製作者の意図をまるでシカトしたかのような配布物やった。
教育言語としてやまとに紹介された時もゲームが作れんと判ってまるっきし相手にさられへんかった言語や。
処理系も入手しずらく動作するコンピュータもなく、モニタ上だけでタートルが動くそら、実際、つまらへんかった。

アランケイは、このロゴちう言語自体やのうて、ロゴを使うて、機械(ロボット)を操作する、ちう考え方に興味を持ったちうわけや。
ゴチャゴチャゆうとる場合やあれへん、要は、ロボットに命令を与える、ちう考え方自体に注目しとった。
命令を与えれば、ロボットは動く。複数のロボットが動く状況も同じ。機械に命令を与える方法として、アランケイは
ごく自然にそれらを考えたちうわけや。
コンピュータに命令を与える際にも、同じことが言えへんか、この発想がオブジェクトモデルの原点や。

ちーとの間して、ある研究員が、この新しい発想にもとづいた代数を説明したちうわけや。なんちうか、
ようみなはんいわはるとこの、

1+1
1.+ 1
1.add 1
1.add(1)

のようなもんやった。休暇中、これらを検証するために当時のBASIC言語で、簡単なモデルを作ってみて、
アランケイに見せてみたちうわけや。

ちーとの間して、この代数モデルが、ホンマに代数として機能するっちうことが判明し、新たな言語が開発される事となりよった。
アランケイは元々simulaをつこうた事があったさかい、そないなアイデアも参考にしたちうわけや。
その結果、スモールトークちうプログラミング言語がゼロックスで開発されたちうわけや。
この言語は、オブジェクト指向言語として、ホンマにロボットに絵を描かせる時のように、コンピュータに文句を伝えて
操作するちうわけや。手続き型プログラミング言語とはまるっきしちゃう。これが今のオブジェクト指向言語の大きな源流となっとる。
したがちう、オブジェクト指向言語では、オブジェクトに文句を与えるゆうアクターモデルとなっとる訳や。

不思議な事に、この言語は機能を拡張しやすい特徴を持ってて、直ぐにGUIの動作するコンピュータが
作られはる事になりよった。これがホンマに現在のマウスとウインドウやらなんやらを使うコンピュータの原点で、ゼロックスで
研究、開発が行われたアルトと呼ぶコンピュータや。
これらのコンピュータ向けに様々なソフトウエアが書かれたちうわけや。

このコンピュータを初めて見ていろたアップルコンピュータの人々が、のちにマッキントッシュと呼ばれるマシンを作るきっかけ
となりよったちう一連の経緯はどエライ有名や。
マッキントッシュは、パーソナルコンピュータの世界で初めてマウスとGUIで操作するコンピュータになった。

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2010年10月01日 10:15