オブジェクト指向

はじめに |   利点 |   クラスとオブジェクト |   階層構造 |   メッセージ


はじめに…オブジェクト指向とは

   オブジェクトとは「物」のことです。現実世界にはいろいろな物があります。例えば、鉛筆や携帯電話などは物です。

   物はその存在意義というか、働きをもっています。そんな側面から物をみると、物には「状態」と「ふるまい」があると言えます。例えば、鉛筆ならその色や太さが状態であり、紙にこすると線が引けるというのがふるまいです。「状態」と「ふるまい」をもって機能する「物」をプログラムを作成する場面に持ち込んだのが、オブジェクト指向です。

   プログラムにも現実世界の物と同様、機能があります。果たすべき役割をもつ「物」を作るがごとく、プログラムの中にオブジェクトを作り、プログラムの機能は果たさせようという考え方です。例えば、絵を描くためのプログラムには、線を引くという機能があります。この機能を実現するのに、鉛筆オブジェクトを作り、線を引く機能を担わせるのです。

   プログラムのオブジェクトも「状態」と「ふるまい」をもち、具体的には、「状態」は「フィールド(変数、プロパティ)」で表し、「ふるまい」は「メソッド」で記述します。


オブジェクト指向の利点

   オブジェクト指向では、プログラムの中に、必要な機能をもつオブジェクトを作り、それらが連絡をとりながら、プログラム全体としての機能を実現します。

   オブジェクトはプログラムを構成している「部品」と言えます。プログラムを組み立てて全体を作る場合、重要なのはその部品がどういう機能をもっているかであり、部品の中がどうなっているかではありません。逆に、部品の中身をいじられると、本来その部品がもっている機能が果たせなくなる可能性があります。

   部品、この場合オブジェクトの中身とは、フィールド(プロパティ)とメソッドです。オブジェクト指向では、部品を使うのに必要なものだけが外部から見えていて、後の部分は外部から隠されて(固い言葉でいうと隠蔽されて)います。これをカプセル化と言います。オブジェクトがカプセルに包まれているという意味です。これにより、いくつかの利点が生まれます。


クラスとオブジェクト

   机の上にある1本の鉛筆は、現実世界で「鉛筆」と識別される「もの」のひとつの実物 です。私たちの頭の中には、「鉛筆と識別されるもの」に関する情報があります。鉛筆が通常もつ状態やふるまいをまとめた鉛筆の「機能概念」いわば鋳型で、その具体的な実物が、目の前の1本の鉛筆です。

   オブジェクトの考えをプログラム作成に持ち込む際にも、同様にオブジェクトの鋳型となる情報のまとまりを考え、それをクラスと呼びます。クラスは、オブジェクトのもつ変数やメソッドをまとめて定義したものです。クラスの定義を構成する変数とメソッドのことをクラスのメンバと呼びます。

   クラスは変数やメソッドを定義した「鋳型」であり、実際の仕事をするのはオブジェクトです。このオブジェクトのことを鉛筆クラスのインスタンス(具体例)とも呼びます。例えば、お絵描きプログラムなら、鉛筆クラスを定義し、そのインスタンスを作り、鉛筆オブジェクトに線を引くように指示します。

   クラスからインスタンスを作るにはnew演算子を使います。
new クラス名(引数)
   括弧の中の引数は,インスタンスを作るときに特別な値を指定する場合に使います。
   多くの場合、new演算子が作ったオブジェクトを変数に格納しておきます。こうすることで、後でオブジェクトのフィールドの値を調べたり、変更したり,オブジェクトのメソッドを実行したりできます。
【注】 オブジェクト指向の代表的な言語にC++とJavaがあります。 上に説明したクラスというオブジェクトの「設計図」を元に、オブジェクトを作るという考えをとっており、クラスベースのオブジェクト指向言語と呼ばれます。
これに対し、JavaScriptはクラスを使わず、既に定義されているオブジェクトを元に固有の機能を追加していきます。クラスベースに対して、インスタンスベース、オブジェクトベースあるいはプロトタイプベースのオブジェクト指向言語と呼ばれます。

階層構造

   プログラムの中では、いくつものクラス(オブジェクト)を使うことになりますが、それらは互いに独立したものではなく機能が似ていることもあります。例えば、お絵描きプログラムの場合、機能として鉛筆の他に、筆、スプレーが必要であるとします。筆もスプレーも、変数として色と太さをもち、線を引くメソッドをもつ点は、鉛筆クラスと共通ですが、筆にはその形状を表す変数が必要で、スプレーは線の引き方が違います。もちろん、これらを独立したクラスとして定義することもできますが、共通部分が重複し、無駄です。
   クラスを別のクラスの機能を受け継いで定義することができます。この例だと、筆クラス、スプレークラスを鉛筆クラスの機能を受け継いで定義するのです。これを「筆クラス、スプレークラスを、鉛筆クラスのサブクラスとして定義する」と言います。筆クラスに対して、上位のクラスにあたる鉛筆クラスをスーパークラスと呼びます。このようなクラスの親子関係がクラス階層です。
鉛筆クラス ─┬── 筆クラス
             │ 
             └── スプレークラス
   サブクラスはスーパークラスのフィールドとメソッドを受け継ぎます。これを継承(インヘリタンス)と言います。筆クラス、スプレークラスは、そのフィールドとメソッドを鉛筆クラスから継承します。この例では、クラス階層は1階層ですが、何階層にも渡って継承関係を作り上げることができます。
【注意】 JavaScriptには,あらかじめオブジェクトが定義されていて, 多くの場合それらの機能を使うことで,処理を記述します。 HTML文書をブラウザにロードすると自動的に作られるオブジェクト(windowやdocument)と,必要に応じて作って使う基本オブジェクト(DataやArray)とがあります。

メッセージ

   オブジェクト指向では、必要な機能をもつクラスを定義し、そのオブジェクトを作り、オブジェクトの間で相互に連絡をとりながら、プログラム全体としての機能を実現します。オブジェクト間の相互連絡は、メッセージをお互いにやりとりすることで、実現します。

   あるオブジェクトが別のオブジェクトのメソッド実行するようにメッセージを送ることで、プログラムの処理が進みます。先の例だと、「鉛筆オブジェクトに線を引くように指示する」とは、鉛筆オブジェクトに対して「線を引く」メソッド(メソッド名をdrawLineとしよう)を実行するメッセージを送ることです。

   メソッドがその仕事をするのに外部からのデータが必要なことがあります。例えば、drawLineメソッドが線を引くには、始点と終点の位置が必要であるというような場合です。これをメソッドへの引数と呼びます。引数はメッセージに含まれて送られます。オブジェクトへ送られるメッセージは、次のような形をしています。
メッセージを送る相手.実行するメソッドの名前(メソッドに必要な引数)
                ↓                ↓           ↓     
              鉛筆オブジェクト.drawLine(線を引く位置)
   メソッドを実行するには、メッセージの受け手であるオブジェクトを表す式を書き、ピリオドに続いて、メソッド名を記述し、その後ろの( )の中に引数を指定します。そのメソッドに引数がないときは空の( )を書きます。

   オブジェクトにメッセージを送ることでメソッドが実行されますが、メソッドの処理が終了すると、メッセージを送ったところ(メソッドを呼び出したとこ ろ)に戻ってきます。この時、呼び出し側にひとつのデータ(計算結果や状態を 表す値など)を返すことができます。これが戻り値です。呼び出し側はこの値を使うことも、無視することもできます。  

   三角関数や四捨五入などの算術的な計算を行うメソッドを集めたMathクラスがあります。例えば、乱数を発生させるメソッドrandomを実行して、乱数を得るには次のように,Mathクラス名に続いてピリオド,メソッド名を書きます。結果として,0から1までのランダムな数値が戻り値として得られます。
Math.random()

   一方,オブジェクトのフィールド(プロパティ)の値を参照するには,オブジェクトを表す式に続いてピリオドを置き、その後ろにフィールドの名前を記述します。
   Mathクラスには、PIという名前のフィールドがあり,円周率の値が格納されています。次のように記述すると,円周率が得られます。
Math.PI

arigat アットマーク acm.org
Last modified: Oct. 2014