![]() ![]() |
クラスは、前にも述べましたが、抽象データ型を実装するものです。この意味は、クラスが、オブジェクトに適用可能な 特徴<feature>(操作)とその特徴の形式的特性とによって性格付けられた、実行時オブジェクトの集合を記述している、ということです。
このようなオブジェクトは、クラスの 直接実例<direct instance> と呼ばれます。クラスとオブジェクトを混乱させてはいけません。つまり、オブジェクトが実行時にだけ存在するのに対して、"クラス" は、コンパイル時の考え<notion>であるということです。これは、古典的なプログラミング言語に存在する、プログラムとそのプログラムの一回の実行との違い、あるいは、型とその型の実行時の値との違いに似ています。
"オブジェクト指向<Object-Oriented>" は、間違った名前であり、 "クラス指向の分析、設計、プログラミング" が、この手法の、より精密な記述であったでしょう。
クラスがどのように見えるかを理解するために、単純な例をお見せしましょう。それは、銀行の口座<account>を記述している ACCOUNT です。しかし、クラス自体の内部を探る前に、クライアント<client> と呼ばれる他のクラスによって、どのように使用されるかを研究することが役立ちます。
クラス X は、型 ACCOUNT の一つ以上の 実体<entity> を宣言することによって、 ACCOUNT のクライアントになることもできます。このような宣言は、次の書式を持ちます。
"実体<entity>" という用語は、"変数<variable>" のより一般的考え<notion>を一般化します。acc のような、参照型で宣言された実体は、実行中のどの時点でオブジェクトへ "アタッチ" してもかまいません。型規則は、このオブジェクトが ACCOUNT の直接実例 -- あるいは、次に見るように、そのクラスの"子孫" -- でなければならない、という意味を含んでいます。
実体は、もしどのオブジェクトへもアタッチされていないのならば、void であると言われます。デフォルトでは、実体は、初期化時に void になります。実行時にオブジェクトを獲得するために、クライアントとなるクラス X に現れるルーチン r は、次の書式の 生成命令<creation instruction> を使用することもできます。
これで、 ACCOUNT の新たな直接実例が作成され、その実例へ acc をアタッチし、そのすべての項目を既定値に初期化します。この表記方法の変種は、以降で研究しますが、デフォルトの初期化を再定義<override>することを可能にします。
ひとたびクライアントが acc をオブジェクトへアタッチしたら、このオブジェクト上で、クラス ACCOUNT において定義された特徴を呼んでもかまいません。呼出し相手として acc を使用する、いくつかの特徴の呼出しには、付加的情報があります。
これらの特徴の呼出しは、target.feature_name という書式のドット表記を使用し、場合によっては、引数並びを括弧で括って続けます。特徴は、次の二種類があります。
ルーチンは、さらに、手続き<procedure> (指令<command>、値を返さないもの)と関数<function> (問合せ<query>、値を返すもの)へ分けられます。ここでは、may_withdraw が、BOOLEAN値を返す関数であり、他の三つの呼び出されたルーチンは手続きです。
クラス X の上記の付加情報は、クラス ACCOUNT において、balance が属性であるか引数の無い関数であるかを示していません。この曖昧さは、内延的<intensive>です。 X といった ACCOUNT のクライアントは、口座がどのように獲得されるか、つまり、口座は、あらゆる口座オブジェクトの属性として格納されているか、関数によって他の属性から計算されるか、ということを知る必要がありません。この二つの技法の選択は、クラス ACCOUNT の仕事以外のなにものでもありません。そのような実装の選択は、しばしば、プロジェクトのライフタイムにわたって変更されるので、それらの影響に対してクライアントを保護することのほうが本質的です。
それでは、クライアントのクラスが一般的にどのように ACCOUNT を使用するかについて、もっと話を進めましょう。次は、クラス
ACCOUNT 自体がどのように見えるかを示す、最初のスケッチです。--
以降から行末までの内容は、注釈<comment>です。このクラスは、その特徴<feature>を導入する、二つの
feature 句を含んでいます。最初の句は、キーワード
feature だけで始まり、さらなる限定子<qualification>を伴っていません。このことは、この句で宣言された特徴が、そのクラスのすべてのクライアントで利用できる、ということを意味します。第二の句は、次のように導入されていますが、
feature { NONE }
次に続く特徴、つまり呼ばれる add 、がどのクライアントからも利用できない 、ということを示しています。中括弧の間にあるものは、対応する特徴を利用できるクライアントのクラスを並べたものです。
NONE は、カーネル ライブラリの特殊なクラスであり、実例を持たないので、 add は、結果的に非公開の特徴<secret feature>となり、クラス ACCOUNT の他のルーチンに対して局所的<local>にだけ利用できます。そのため、 X のようなクライアント クラスにおいては、acc.add( -3000 ) という呼出しは、無効であるでしょう。
順番に、これらの機能を吟味していきましょう。is ... do ...end は、ルーチンを属性から区別します。そのため、ここで、クラスは、属性として balance(残高) を実装しましたが、注意したように、同じく関数としても受け入れることができるでしょう。また、owner(所有者) という特徴は属性です。
言語の定義は、自動的初期化を保証しているので、account オブジェクトの初期の balance は、生成命令の後ではゼロになっているでしょう。それぞれの型は、デフォルトの初期値を持っており、初期化のために使用されます。つまり、 INTEGER(整数) と REAL(実数) に対しては零、 BOOLEAN(真理値) に対しては false(偽)、 CHARACTER(文字) に対しては null(空値)、そして参照型に対しては void の参照です。また、クラスの設計者は、この例を改訂した下の例で示すように、クライアントに異なる初期化オプションを提供することもできます。
他の公開された特徴である open, deposit, withdraw と may_withdraw は、見たとおりのルーチンです。特殊な実体である Result が may_windows で使用されていますが、関数の結果を明示するためのものです。関数の入り口で、関数の結果の型の既定値へ初期化されています。
非公開の手続きである add は、公開された手続きである deposit と withdraw の実装のために働きます。すなわち、ACCOUNT の設計者は、この手続きを、それ自体によって公開されるには、あまりに一般的であると判断したのです。is 1000 という句は、minimum_balance を、クラスの実例の中に記憶域を一切占有しない定数<constant>の属性として導入しています。これとは対照的に、あらゆる実例は、balance といった、あらゆる定数でない属性に対しては領域<field>を持ちます。
Eiffel のオブジェクト指向のプログラミング スタイルでは、どんな操作も特定のオブジェクトに対して相対的です。その操作を呼び出しているクライアントにおいて、このオブジェクトは、acc.open における acc のように、対応する実体をドットの左側に書くことによって指定します("Jill" )。しかしながら、そのクラスの中で、"current" という、操作が適用されるものへの実例は通常暗黙的なままなので、open という手続き内の owner または deposit 内の add といった、限定されていない特徴の名前は、「owner という属性または add というルーチンが現在の実例へ相対的である」 ということを意味します。
もしあなたが現在のオブジェクトを明示的に示す必要があるならば、特殊な実体 current を使用することもできます。たとえば、上記のクラスに現れる add の限定されていない発生<occurrence>は、current.add と等価です。
いくつかの場合に、中置演算子または前置演算子の表記方法は、ドット表記よりもいっそう便利でしょう。たとえば、もしクラス VECTOR が追加のルーチンを提供するならば、大多数の人々は、v.plus(w )というドット表記の呼出しよりも、v + w という書式の呼出しの方が、より快適であると感じるでしょう。これを可能にするためには、そのルーチンに、plus というよりもむしろ infix "+" という書式の名前を与えるだけで十分です。しかしながら、内部的には、相変わらず、その操作は、通常のルーチン呼出しのままです。前置演算子は、同じように、利用できます。
上記の単純な例は、この言語の基本的な構造化の機構、つまりクラス、を示していました。クラスは、クラスの特徴のいくつかを構成する公式のインターフェイスを通じて、クライアントがアクセスできるデータ構造を記述します。特徴は、属性またはルーチンとして実装されます。公開<export>された特徴の実装は、他のもの、すなわち非公開の特徴へ頼ることもできます。
![]()
URL
for this page: http://www.eiffel.com/doc/manuals/language/intro/classes.maker.html.
Copyright 1994-1998 Interactive Software Engineering Inc. All rights reserved.