List 1 2 生クラスがもっメンバ変数て、あるからメン バ関数 eset から直接参照て、きる。また , 基本 クラスの公開部にあったメンバ関数 dset も関 数 eset から呼び出すことがて、きる。しかし , 基本クラスの非公開部にあるメンバ変数へ は , 派生クラスのメンバ関数からは直接参 照て、きず , 基本クラスのメンバ関数 dset をと おして参照する。つまり , 「 class クラス名 : 基本クラス」の形式の場合は , 基本クラス の公開部 / 非公開部がくずれず , 派生クラス の非公開部に受け継がれることになる。 派生クラス 2 ( 「 class クラス名 : public 基 本クラス名」 ) の場合は , 基本クラスの非公 開部は派生クラスの非公開部に , 基本クラ スの公開部は派生クラスの公開部に受け継 がれる。派生クラスの公開部には , 基本ク ラスの公開部にあるメンバ関数もあり , 外 部から呼び出すことがてきる。ただし注意 しなければならないのは , 基本クラスのメ ンバ関数を外部から呼び出すことはてきる が , そのメンバ関数がアクセスて、きるのは 基本クラスのメンバ変数だけだということ て、ある。これは , 派生クラスのメンバ関数 にもあてはめられる。派生クラスて、のメン バ関数は , 派生クラスによって追加された メンバ変数しか参照て、きない 基本クラスより新しいクラスを派生させ る場合は , List 9 , List 10 のように , 基本 クラスのメンバ変数やメンバ関数を派生ク ラスからどのように扱うか , 使用目的に応 じて選択することになる。 , こては , 基本クラスから一つの派生ク ラスを導いたが , 派生クラスを基本クラス として , さらに新たなクラスを派生させる ことがてきる。このことにより , クラスの 階層構造が実現て、きる (Fig. 9 ) 。 派生クラスには「プロテクテッド (protected : ) 」と呼ばれる機能がある。このプロテクテ ッド機能は , クラス内のラベルとして使用 ラスを派生させる時点て、基本クラスに対し の派生クラスのメンバ関数からて、も直接ア する (Fig. 1 の。 クセスて、きるメンバを指定するものて , 指 て「 public 」とすることて、 , どのメンバ関数か 定されたメンバを「プロテクテッドメンバ」 らても直接アクセスて、きるが , 外部からの ヾ protected : 〃は , 派生クラスによってクラ 直接アクセスは許きれていない。クラスを スの階層構造を実現するような場合に , ど などと呼ぶ。プロテクテッドメンバは , ク 工 11 っ 0 十 a. 0. れ 0 ー 8 0 14 11 1 よ 11 11 っ 0 っ朝 List 13 1 : #inclßde 2 : # i ncl ude 3 : c 1 ass A 4 : i nt a ; 5 : public: 6 : VOid 7 : VOid 8 : 9 : 10 : } : A { 12 : c I ass B : 13 : int 14 : public: VOid 20 : 22 : 23 : } : 24 : 25 : m a i n ( ) x. s et ( 5 ) : 28 : x. print() 29 : 30 : } く stream. h> く stdio. h> s et ( i nt i ) { a ー print() { printf(" a = %dYn" b : set(int i) { A : : set ( i ) : p r i nt ( ) { A : : pr i n t ( ) ; printf(" b ニ %dYn" VO i d Fig. 7 List 8 の構造 YY dd bp name aoe 78 C MAGAZINE 1991 4
拡張 C の C + + 定義する場合に非公開部と公開部があり , 操作することがて、きないと解釈てきる。外 スされる。このことにより , C 十十のクラス 部からは , メッセージ式によってデータ操 非公開部のデータは外部の関数から直接ア がこの情報隠蔽の機能をもっていることに 作を行うことになる。 C 十十て、は , クラスを クセスてきず , メンバ関数によってアクセ なる。 C 十十での派生クラスか クラス階層 クラス階層は , データの抽象化の程度に よって階層化し , 上位に階層情報を継承す ることて、 , C 十十て、は , データの抽象化はク ラスによって行われ , 階層化は派生クラス て、実現て、きる。 0 オプジェクト指向の基本的な構成要素は , ほかにもあるが代表的なものを C 十十の機能 と比較することがてきる。このようにオプ ジェクト指向の考え方てプログラミングを 行うための構成要素カ℃十十にも備わってい ることから , C 十十ても「オプジェクト指向 プログラミングがて、きる ( 可能だ ) 」といえる のて、あろう。 なお , 本連載の最後として , クラスを用 いた簡単なプログラムを付録ディスクに収 録した (SAMPLE. CPP)O 参考にしていただ 本連載の最初にも述べたが , C 十十はあく まても C 言語の拡張版てあり , C 言語の機能 に新しい機能を組み込むことて生まれた新 しい言語てあるといえよう。新しい機能を 組み込む過程て , オプジェクト指向の考え 方によるプログラミングを実現するための 機能が組み込まれたものてあって , オプジ ェクト指向プログラミング言語として設計 された言語て、はない 0 解説の中てはオプジェクト指向とかオプ ジェクトといった表現をあえてさけてきた。 また , C 十十のバージョンによる違いなどを 明らかにしないまま説明した。そのために 表現がうまく伝わらなかった箇所もあった ように思われる。この点 , お詫びするしだ いてある。本記事が今後 C 十十を取り入れよ うとする C 言語ューザの役に並てば幸いて、あ 1 1 : c lass A { 2 : int A() { a ま 4 : print() { VOid printf( ” a = %dYn" 6 : 7 : i nt 12 : 13 : VO i d 14 : 17 : c 1 ass C い A i nt 19 : public: 20 : print() { VOid printf(" c 言 %dYn" 22 : 23 : 24 : } : 25 : main() 28 : 29 : 30 : p->print(); 32 : 33 : B : b : print() [ printf(" b = %d*n ” List 1 : c 1 ass A { i nt a : 3 : public: 4 : print() { virtual VO i d 5 : printf( ” a = %d*n ” 6 : 7 : 9 : c 1 ass B : A int b : 11 : public: print() { VO i d printf(" b = %d%n" 14 : 17 : class C: A int 19 : public: 20 : print() { VO i d printf(" c %d%n" 23 : 24 : } : 25 : main() 26 : { A* p: 28 : 29 : 30 : p->print() : 32 : 33 : 0 拡張 C としての C 十十 81
拡張 C として の C + + 派生させるとき , 基本クラスに対し public の 同じ名前にしたほうがプログラムが見やす 仮想関数 指定を行わない , 基本クラスのすべてのメ くなる。このように , 派生クラスの中から , 同じ名前の基本クラスのメンバ関数を呼び ンバを派生クラスの非公開部に置く場合は , 出す場合に , スコープ演算子「 : : 」を用いる 基本クラスのプロテクテッドメンバは派生 仮想関数は , 派生クラスを用いる場合に (List 13 の 20 行目 ) 。 クラスの非公開部に置かれてしまう (List 使用され , プログラムの実行時に決定され こまて、解説してきた派生クラスは , る型 ( クラス ) のメンバ関数を呼び出す機能 11 , List 12 ) 。 つのクラスをもとに新しいクラスを派生さ ( メカニズム ) て、ある。派生クラスては触れ 派生クラスを使用するプログラムて、は , せるものて、ある。 しばしば , 基本クラスのメンバ関数と同じ なかったが , 派生クラスのポインタは基本 いくっかのクラスを組み合 名前のメンバ関数を派生クラスにもっこと クラスへのポインタ変数に代入することが そのほかに , せるような形式て、新しいクラスを派生させ て、きる (List 14 ) 。 がある。 List 9 のように , 基本クラスのメン る機能がそなわっているが , 誌面の関係て、 このとき , p->print() として関数の呼び バ変数を表示するメンバ関数と派生クラス 割愛する。 出しを行うと , 基本クラスのメンバ関数 print のメンバ変数の値を表示するメンバ関数は , Fig. 8 基本クラスと派生クラス 基本クラス class date int yy, mm, dd; public : dset( ) VOid 派生クラス 2 public date 派生クラス 1 class employee name[20J; Cha 「 i nt age; public: VOid class employee name[20]; Cha 「 i nt age; public: VOid d ate eset( ) eset( ) 非公開部 公開部 拡張 C としての C 十十 79
List 20 : 18 : 15 : 14 : 12 : 10 : 7 : 6 : 5 : 4 : 3 : 2 : 1 : LiSt 24 : { 30 : } 1 : 1 : 4 : 6 : 7 : 8 : 9 : 13 : 20 : 21 22 : 25 : 26 : 28 : 29 : 23 : main() #include 2 : #include 3 : c lass A int a; 5 : pub ⅱ c : VO i d VO i d 12 : class B:public A{ int 14 : pub ⅱ c : VO i d VO i d く stream. h> く std i 0. h > aset(int i) aprint() { printf(" bprint() bset(int { a printf(" b ニ %dYn ” x. aset ( 3 ) : x. bset ( 5 ) : x. aprint() : x. bprint() class int protected : int public: VO i d class B int protected: int public: VO i d List 12 VO i d 14 : public: int 12 : protected: int class VO i d 5 : pub ⅱ c : int protected: int C lass 10 : 8 : 7 : 4 : 3 : 2 : aset(int a set ( i + 3 ) : P a i + 2 : set(int i) { b : :public A set(int b : aset(int 拡張 C の C + + は行えない ・引数は一つて , 必ずフレンド関数を定 義しているクラス変数て、なければなら 単項演算子の多義化 のンバ関数による ては , 非公開部のメンバはどのような扱い からはこの関数だけを呼び出すことになる。 のはメンバ関数 eset ( ) のみてあるから , 外部 受け継がれる。派生クラスの公開部にある バ関数も , すべて派生クラスの非公開部に イベートなメンバ変数もパプリックなメン 派生クラス 1 の場合は , 基本クラスのプラ の方法て、派生クラス employee を定義してい Fig. 8 を見ていただきたい。ここては二つ 義する。 基本クラスとして派生クラス employee を定 ず , 日付をクラス date とし , クラス date を スによって employee を定義してみたい。ま List 8 を , クラスを用い , さらに派生クラ 用いる。 , こて、は , 「基本クラス」 , 「派生クラス」を 「派生クラス」 , 「導出クラス」などと呼ぶ。 本クラスから作り出される新しいクラスを ラス」 , 「基底クラス」などと呼ぶ。また , 基 クラスにおいて , 元になるクラスを「基本ク えることがてきる ( まず最初の段階として ) 。 を作り出すことは , 構造体と同じように考 クラスて、も一つのクラスから新しいクラス て他の構造体を入れ子にすることがて、きる。 げると , List 8 のように構造体のメンバとし す機能を解説する。まず , 構造体を例にあ ーっのクラスから新しいクラスを作り出 派生クラス ・引数はない ー ) の多義化を行える ・変数の後ろにくる単項演算子 になるか ? メンバ変数 name と age は , 拡張 C としての C 十十 派 77
Fig. 9 クラスの階層構造 cl ass A i nt public; class Ba int public; class Ca i nt public, class Dba ;B i nt public, class Eba ;B i nt public; d; C, ;A b; ;A class Dba class Ba class class Eba Ca class を呼び出すことと解釈される。しかし , ポ インタ変数は , クラス B の変数を指している から , クラス B のメンバ関数を呼び出した とになる。このような問題を解決するため の機能が「仮想関数」てある。つまり , ポイ ンタの型と実際の型が異なっていても , プ ログラムの実行時にもっている型のメンバ Fig. 10 プロテクテッド class クラス名 { 非公開部 protected ; プロテクテッドメンバ public: 公開部 80 C MAGAZINE 1991 4 関数を呼び出すメカニズムてある。仮想関 数にしたいメンバ関数は , 基本クラスて、 「 virtual 」によって宣言する (List 15 ) 。仮想 関数と定義て、きるのはメンバ関数だけて、あ List 15 ては , 基本クラスのポインタ変数 にクラス B の変数 x のポインタが代入されて おり , 基本クラスの定義て、メンバ関数 print が仮想関数として宣言されているために p->print( ) て、は , クラス B のメンノヾ関数 print が呼び出される。 C 十十によるオフジェクト指可 プロクラミンクベのアプロ 最後に , オプジェクト指向の考え方によ るプログラミングを行うために必要な要素 と C 十十の機能を比較し , C 十十て、のオプジ ェクト指向プログラミグとは , どのような 形式になるか考えてみたい。 オプジェクト指向の基本的な構成要素は , 「オプジェクト」「メッセージ」「クラス」「イン スタンス」「情報隠蔽」「クラス階層」などて、あ ろう。オプジェクト指向プログラムて、は , オプジェクトにメッセージを送り , 受け手 側はメッセージによって処理を決定する。 この流れて、プログラムが実行される。 C 十十のクラス」かオフジェクト指向の 「オフジェク村 オプジェクト指向におけるオプジェクト とは「データと手続きの融合体」と定義され ている。 C 十十のて、クラスはメンバ変数にデ ータがあり , メンバ関数がそのデータへの 手続きて、ある。 C 十十でのメッセージ式は , クラス変数・メンヾ関数 ( 引数 ) オプジェクト指向プログラムは , オプジ ェクトにメッセージを送ることて、実行され る。メッセージは , オプジェクトに対して 動作の指示とみることがて、きる。「オプジェ クト」に相当するものが C 十十の「クラス」て、 あるとすると , オプジェクトにメッセージ を送る ( メッセージ式 ) ことが , 「メンバ関数 の呼び出し」といえる。 C 十十のクラスかオプジェクト指向での クラスであり , クラス変数がインスタ オプジェクト指向のクラスとインスタン スは , あるデータ型のデータに関する仕様 , つまりデータ型を「クラス」 , そのデータ型 て、割り当てられた領域や実データを「インス タンス」としていることから , C 十十の「クラ ス」がオプジェクト指向の「クラス」にあては まり , 「インスタンス」は , 「クラス変数」と みることがて、きる。 情報隠蔽の機能を C 十十はクラスによって実現 オプジェクト指向において , 情報隠蔽と いう言葉はよく用いられる。情報隠蔽は , オプジェクト内部のデータは外部から直接
拡張 C の C + + Fig. 4 List 3 の構造 Fig. 3 List 2 の構造 クラス B メンバ変数 メンノヾ変数 メンノヾ変数 クラス C メンバ変数 メンバ変数 メンバ変数 クラス E クラス D メンバ変数 メンバ変数 メンバ変数 メンバ関数 メンバ変数 メンバ変数 メンバ変数 メンノヾ関数 a メンノヾ関数 b レ フ フレンド宣言 友 達 ン レ フ 友 達 関 数 LiSt List 「いいににいにいいいいー、にいをい町いーにーいい C : 1 : c lass 2 : c I ass 3 : int 4 : public: friend int add (B&, (&) : 5 : 7 : 引 ass 8 : int 9 : public: friend int add (B&, (&) : 12 : int add()& b, C& c) 13 : { return( b. x 十 c. y); 14 : 1 : c lass 2 : int 3 : public: friend int cmp(x&, (&);// フレンド関数の宣言 4 : set(int i) {a VO i d 7 : i nt cmp ()& r , x& t ) / / 関数の定義 ret urn ( r. a==t. a) : / / プライベート・メンバの参照 9 : 10 : } 11 : main() m. set(5); 13 : n. set(7) : 14 : i f ( ! cmp ( m , n) ) { List 2 , List 3 の 1 行目の class C; や class トにアクセスしてもかまいませんよ」といっ 数 add 内て、は , 各クラスのメンバ変数を直接 E; は , クラスの「定義」がまだ行われていな ているのてある。 参照て、きる。さらに , メンバ関数をほかの この宣言によって友達になった関数をフいが , 「定義」の前てクラスを使用するため クラスのフレンド関数にすることも可能て、 にクラスの「宣言」を行う記述てある。 レンド関数と呼ぶ。 ある。 メンバ関数をほかのクラスのフレンド関 数にする場合は , クラスの定義とは別にメ ンバ関数の定義を行わなければならない (List 3 参照 ) 。なお , メンバ関数の定義は , フレ ンド関数として宣言するクラスの定義の後 て記述しなくてはならない List 3 ては , クラス D のメンバ関数 d t を クラス E においてフレンド関数として宣言す ることにより , メンバ関数 dset 内て、引数によ って指定されるクラス E のメンバ変数を直接 アクセスしている。つまり , friend の宣言に よって , 「関数さん , 私 ( クラス ) があなたの 友達になってあげるから , 私のプライベー List , 0 0 0 C— 0 0 、 1 っ 0 00 -4 ・ - -0 7 ー 8 0 》 01 よっ 0 っ 0 4 戸 0 ^ 0 行ー 8 D::dset()* e) 拡張 C としての C 十 + 73
拡張 C としての C 十十 クラスは , テータのほかに関数をメンバにすることができ , メンバの初期化や消去を行う ための機能により , 誤った結果を得るようなバグを防ぐことか可能になるなどの基本機能 (Fig. 1 参照 ) のほかに , いくつかの応用機能か備えられている。今回は , クラスの応用機能 について解説し最後にオプジェクト指向での考え方と C 十十の機能を比較する。 龍崎昌平 く第 3 回〉クラスの応用 2 関数 cmp の定義は , メンバ関数の定義て、は ・フレンド関数は , 通常の関数て、ある ( メ フレンド関数 なく , 通常の関数定義て、ある。したがって , ンバ関数をフレンド関数にすることが て、きる ) 本来ならば引数て、指定されるクラス変数内 のプライベートなメンバ変数に直接アクセ ・フレンド関数として宣言することて、 , フレンド関数はメンバ関数を使用せず構 スて、きず , アクセスするためのメンバ関数 クラス変数内のメンバ変数に直接アク 造体のように , 一般の関数内からクラス変 が必要となる。しかし , 関数内て、は構造体 セスて、きる 数がもっプライベートなメンバ変数へ直接 のように「クラス変数名 . メンバ変数名」の書 List 1 て、は , 関数 cmp を一つのクラスのフ アクセスて、きるものて、 , メンバ関数を定義 レンド関数に宣言したが , 複数のクラスか する際にキーワード friend 〃によって定義さ 式によってアクセスが行われている。この ような記述は , クラスの定義時に「通常の関 ら一つの関数をフレンド関数にすることも れる 0List 1 は , メンバ変数の比較を行う関 て、きる。 List 2 て、は , クラス B とクラス C が 数をクラスの友達 ( friend ) にしてあげる」とい 数をフレンド関数として定義している例て、 関数 add をフレンド関数としているため , 関 う宣言をすることよって可能になる。 ある。 Fig. 2 List 1 の構造 クラス A Fig. 1 クラスの基本機能 class 名前 { コンストラクタの定義 / 宣言 ティストラクタの定義 / 宣言 公開部 (public) メンバ関数の定義 / 宣 = 関数の型名前 : : 関数名 ( 引数のリスト ) メンバ関数内では , メンバ変数名だけの記 述によりメンバ変数へのアクセスが行える ーここ」非公開部 (p 「 ivate) メンノヾ変数 メンバ変数 メンバ変数 public; レ フ 友達 ↓ main( ) 関数 名前変数名 ; 変数名 . 関数名 ( 引数のリスト ) ; 72 C MAGAZINE 1991 4
多義化可能な演算子 演算子のオ→ヾローラング 演算子のオーバローディング ( 多義化 ) は , C 十十の演算子をクラスどうして、演算て、きる ようにするものてある。 C プログラムて構造 体を使用する場合に構造体変数て、の演算を 行いたいときがあるが , 許される演算は単 純代入だけてある。 C 十十のクラスについて も同様てあり , List 4 のようなクラス変数て の比較は誤りとなる。このような場合は , 演算子のオーバローディングを行うことて , クラス変数による演算が可能になる。 クラス変数どうして演算を行うような場 合に , 演算子「 = = 」をクラスにも適応てき るようにするのが演算子のオーバロードて ある 0List 5 はクラス String ての比較を行う ための例てある。クラス内のフレンド関数 の宣言て演算子のオーバロード ( 以降 , 多義 化 ) を行っている。また , 関数 main 内の if 文 て基本のデータ型と同様に , クラス変数て 比較を行っている。ここぞは , 演算子「 = = 」 が多義化されていることによって文法的な 誤りてはなくなる。演算子を多義化するた めには , キーワード「 operator 」を用いる。 このキーワードに続けて演算子を記述する ことて多義化される。 演算子の多義化は一種の関数定義になる (List 5 参照 ) 。つまり「。 rat 。 r 演算子」は関 数名と見ることがてきる。したがって , 叩 era tor 演算子の ( ) 内が引数となる。 List 5 て は , 二つのクラス String の参照を引数とする 一般の関数「 operator = = 」がフレンド関数 てある。関数「 0 rator = = 」はフレンド関 数てあるため , クラス String 内のメンバ変数 を直接アクセスし , メンバ変数が同一てあ れば「 1 」を , 異なっていれば「 0 」を戻り値と する。プログラムの実行時は , 式「 x の評価を行う時点て関数「 operator = = 」が 呼び出される。演算子の左辺が関数の最初 の引数となり , 右辺が 2 番目の引数となる。 多義化てきる演算子は , C 十十に最初から備 6 : 10 : } : 74 C MAGAZINE 1991 4 Fig 十 Fig. 6 5 くく = new delete ニ項演算子と単項演算子 ニ項演算子 メンバ関数 List フレンド関数 メンバ関数 単項演算子 フレンド関数 クラス変数 1 . ope 「 ato 「演算子 ( クラス変数 2 ) operato 「演算子 ( クラス変数 ) クラス変数 . ope 「 ator 演算子 ( ) operato 「演算子 ( クラス変数 1 , クラス変数 2 ) 1 : 2 : 3 : 4 : 5 : 7 : 8 : 9 : 14 : String { C lass int I en : Char public: void set (char* p) { strcpy( s, p) : S ー new char 厄 n + 1 ] : len = strlen p ) : 1 1 : ma i n ( ) Strin そ Raioneru"); X. set Y. set("Toshihiko Akama") :
りがたい。 Fig. 1 に , SmaIItalk-80 と Smal ltalk / V のデータ構造を示す。 これらのクラス階層を見て感じることは , SmalltaIk/V は SmalltaIk ー 80 Ver. 2.0 あ たりの比較的初期の仕様を参考にしている らしく , 以降のバージョンて追加されたク ラス , とくに Ver. 2.2 から追加された Model という対話的アプリケーションを作る場合 に重要なクラスが存在していないのが目に つく。変数なども , 以降の SmaIItaIk-80 て、 は削除された , 外部ファイルを管理する大 域変数 Disk などが残っていたりする。 クラス構成て、 , Smalltalk-80 と SmaIItaIk/ V て、もっとも異なる印象を受けるのは , ウィ ンドウなどのユーザインタフェイスまわり て、ある。 Smalltalk-80 は , ウインドウを構 築する場合 , MVC モデルという枠組みによ って記述する。これは , 論理モデルてある ということが特徴て、ある。論理モデルて、あ るため , ウインドウのプロセスとはまった 言て、いって , ウインドウ く関係がなく , システムの機能をオプジェクトによってモ デル化したものて、ある。しかし , これには 言語仕様のレベルて、の解説がまったく存在 しない。そこて、 , 各プログラマがソースコ ードを解読しながら , 理解していくという ことになる。これは , MS-DOS 版の Smalltalk ー 80 て、もまったく同じて、あり , まずこの MVC モデルを理解しないかぎり ,SmaIIaIk-80 て、 アプリケーションを組むことは事実上不可 Fig. 2 Sm 訓 ta ⅸー 80 の MVC モテルと Sm 訓 ta ⅸ / V の MPD モテルの階層 Smalltalk-80 Controller MouseMenuController StandardSystemControIIer BitEditor FormEditor ScreenControlle 「 Scr 引℃ ont 「 0 「 ListController SelectionlnListController ParagraphEditor TextEditor StringHoIderController TextCollectorController TextController CodeControIIer NoController SwitchControIIer View StandardSystemView ListView SelectionlnListView StringHoIderView TextCollectorView SwitchView BooleanView TextView CodeView FormView FormHolderView SmalltaIk/V Dispatcher TopDispatcher GraphDispatcher Sc 「 eenDispatche 「 ScroIIDispatcher ListSelector TextEditor PromptEditor PointDispatcher Pane TopPane SubPane ListPane TextPane GraphPane 最新ロのロロレポート 能て、ある。本稿の内容からはずれるため , MVC モデルの詳細な解説は省略するが , 簡 単にいうと , MVC とはモデル ( Model ) , ビ ュ—(View), コントローラ (Controller) の各 頭文字を取ったものて、 , 演算 ( またはデータ 管理 ) , 表示 , 入力という各機能をもった , 三つのオプジェクトによって , ーっのウィ ンドウシステムを構成する技法てある。ク ラス名や定義の詳細は異なっているが , の MVC モデルという基本的な枠組みは , SmaIItaIk/V< も同じて、あり , View に相当 するクラスとして Pane, コントローラに相 当するクラスとして Dispatcher が存在する MPD モデルということになろうか。 Fig. 2 に , SmalltaIk/V の MPD モデルと , Smal ltalk ー 80 の MVC モデルのクラス階層とその 対応を示す。 SmalltaIk/V には , 演算の本体て、ある Model というクラスは存在しない。そのた め , 新たにアプリケーションて、ウインドウ システムを定義する場合 , Smalltalk/V て、は クラス Object のサプクラスとしてモデルを 定義することになるが , Smalltalk ー 80 ては クラス ModeI のサプクラスとすることになる という違いがある。これは , 具体的には , ウインドウの動きの伝達メカニズムてある , 依存性 (Dependensy) をどのように管理する かというプログラム上の違いになるが , MVC モデルの詳細なメカニズムについては , 「ウインドウシステムのプログラミングパラ ダイム」 ( 中川幸男著 , fSuper ASCII 』 ,90 年 1 月号 ~ 2 月号 ) を参照していただきたい。ウ インドウシステムについても , SmaIItaIk- 80 のクラス階層に比べ , Smalltalk/V のもの は非常に簡潔なものになっている。しかし , ウインドウとしての表現力は SmaIItaIk/V は それほど劣るものてはなく , 部品として機 能するウインドウとしては , スイッチ様の BooleanView が足りないだけてある。これ は ,Smalltalk/V のウインドウはすべてプラ ガプルビュ ーという , 抽象度の高いクラス 構成になっているため , SmaIItaIk-80 より 最新開発環境レポ も簡潔に記述てきるからてあろう。プラガ ート 125
1 ) 。おもなものを説明すると , ①インスタ ンス変数への値の代入 , ④メソッドの呼び 出しと復帰 , ⑧ ReadStream の読み込み , ⑩ グラフィック操作 , ⑩逆コンパイル , ⑩ク ラス階層の探索 , そして⑩インスタンス生 成てある。各処理を何回か繰り返し , その 結果から処理の単位時間などを導き出した のが TabIe 1 の各値て、ある。単位は記載がな いものは microseconds<, いずれも筆者の 実測した値てあるが , ディスクやメモリの 状態によって若干の差が出ることがある。 なお , 富士ゼロックス 1161 , 1121 と , 富士 ゼロックス情報システム SPARCstation, PC ー 9801 , J ー 3100 て、は , コンパイラに若干の違 いがあり , 筆者がプログラムに修正を加え たものてあることを付記しておく。 項目によってばらっきがあるため , 各処 理系の一般的な傾向についてはなんともい えないが , これを見るかぎり , MS-DOS 版 SmaIItaIk-80 は , SPARC などのワークステ ーションは別格としても , 名器といわれた 富士ゼロックス 1121 をかなり超えたパフォ ーマンスてあるといえるてあろう。現在の 高度なワークステーションと , 一世代前の AI ワークステーションの中間的な存在とい えるてあろうか。 ソッド比較 クラスとメソッド群を Table 2 に示す。実 際に Smalltalk/V て、プログラミングを行って いて感じたのだが , Sma Ⅱ talk / V には , クラ スメソッドに , クラスの簡単な動きを示す ようなメソッド「 example 」がほとんど含まれ ていない。そのため , プログラムのドキュ メント性は , 若 +Smalltalk-80 よりも劣る が , そのぶん添付のマニュアルが Smalltalk ー 80 よりも優れている。 Smalltalk ー 80 のマニ ュアルはほとんど日本語訳されておらず , MS ー DOS 版のために書き加えられた部分 ( も ちろん日本語てあるが ) は , マニュアル全体 の 10 % にも満たない。 Smalltalk ー 80 のマニ 1991 4 ュアルに関しては , 富士ゼロックスが , 1121 124 C MAGAZINE などのワークステーションとともに , Smal ltalk ー 80 を扱っていたころからあまり充実し ているとはいえない。しよせん , Smalltalk ー 80 に関しては , プルーブックやオレンジプ ックを超えるドキュメントは作り得ないと いうことか。あるいはソースコードを読む しかないというべきか。 SmalltaIk-80 は , 機種に依存した部分を 除けば , パソコン版て、あっても , ワークス Table 2 クラス , メソッド群 クラス テーション版と同じクラスをもっているが , SmaIItaIk/V は SmaIIta ト 80 に比べてかなり クラスの数が少ない。しかし , オプジェク ト指向てプログラミングを行うための重要 なクラスは一通りそろっている。とくに Smalltalk ー 80 ていちばんすばらしいといわ れるデータ構造に関するクラス (CoIIection) は , おおまかな枠組みが Smalltalk ー 80 に準 拠しているため , プログラマには非常にあ SmaIItaIk/V(MS-DOS) SmaIltaIk/V 286 SmaIItaIk-80(MS-DOS) Fig. 1 Smalltalk-80 と Smalltalk/V のテ SmaIItaIk/V Collection Bag lndexedCollection FixedSizeCollection Array B yteArray lnte Ⅳ引 String Symbol OrderedCollection SortedCollection Set Dictionary ldentityDictionary MethodDictionary SystemDictionary 128 358 ータ構造 インスタンスメソッド 1924 Smalltalk-80 5938 2217 MappedCollection Bag Collection クラスメソッド 229 12 51 279 SequenceableCoIIection Ar 「 ayedCollection A rray ScannerTable ByteArray CompiIedMethod RunA 「 ray String ByteString Symbol ByteSymbol WordSymboI WordString Text WordArray DisplayBitmap lnte Ⅳ引 OrderedCollection SortedCollection S et Dictionary IdentityDictionary