Javaプログラミング基礎

講義資料

オブジェクト指向プログラミング(2) - オブジェクト指向の概念

オブジェクト指向の概念

Java は「オブジェクト指向 (object oriented) 」のプログラミング言語です。 オブジェクト (object) とは日本語で「モノ」のことです。 オブジェクト指向の概念においては すべてがモノを中心とした考え方をします。 オブジェクト指向概念について詳しく考えてみましょう。

オブジェクト

「オブジェクト」はオブジェクト指向を理解する上で重要な概念です。

現実世界では、犬、机、パソコン、自転車など身の回りにオブジェクトの例を 見ることができます。 このような現実世界のオブジェクトには、 すべて「状態」と「振る舞い」を持つという特徴を備えています。 例えば、犬には状態 (名前、毛色、種類、空腹) があり、 振る舞い (吠える、歩く、お手をする、ひっかく) があります。

プログラムの世界では、オブジェクトは変数で状態を持ち、 メソッドと呼ばれるオブジェクトに関する処理をひとまとめにした処理単位で 振る舞いを実現します。

プログラムの世界でオブジェクトを用いると、 プログラムの中で扱う様々な対象物をプログラムの中に書くことができます。 住所録の個人データを表すオブジェクトや、 RPGにおける登場人物やアイテムを表すオブジェクトなどです。 また、オブジェクトは画面上のアイコン、ボタンやウィンドウなど GUI (Graphical User Interface) の表示部品を表すためにも使われます。 さらに、抽象的な概念を表すのにも使われます。 マウスのボタンが押されたという行為、 プログラムでエラーが起ったという事態、などです。

どのようなものがオブジェクトになるかを見出し、 その特徴を分析することは重要な問題です。 ここでは、オブジェクトの 2 つの特性について説明します。

1. 属性

オブジェクトは、固有の姿、形、性質などを持っています。 このようなオブジェクトの状態は、属性として表現されます。

プログラムの中では、プログラムに登場する対象物をオブジェクトとして表現します。 先ほどの住所録システムでは、一人の個人を表わす情報がオブジェクトになります。 また、ブログのシステムでは1つの記事がオブジェクトなりそうです。 夏休みにボールのシミュレーションを行うプログラムを作成しましたが、 プログラムに登場するボールもオブジェクトとして扱うことができるのです。

これらの属性の値がそのオブジェクトのアイデンティティとなるわけです。 オブジェクトは属性の値によって 他のオブジェクトに対して明確に区別することができます。 オブジェクトは固有の属性値を持つ唯一の存在であると 考えることができます。 このような「固有である」という性質も オブジェクトの重要な特性の一つなのです。

Java では属性を変数として表します。

2. 操作

各オブジェクトは固有の振る舞いを持ちます。 これを操作 (operation) と呼びます。 操作は一般的に動詞で表現されます。

例えば住所録であれば、住所を登録する、住所を検索する、住所を表示する という操作を考えることができます。 ブログのシステムでは記事を登録する。コメントを登録するなどです。 また、これらの操作にはパラメータが必要となります。 住所の登録であれば「何を登録するか」、 ブログへの記事登録であれば「記事の内容」です。

Java では操作をメソッドとして表します。 メソッドとはプログラムの一部分をひとまとまりにして、 ある機能を実現するように一つの単位としてまとめたものです。 (メソッドのことをまれにメンバ関数と呼ぶこともありますが、 これは C++ 等の別の言語での呼び方)

メソッドを実行するためには、以下の情報が必要です。

  1. メソッドを実行する対象のオブジェクト名
  2. 実行するメソッドの名前
  3. メソッドに必要なパラメータ

住所録の例で考えてみましょう。

  1. 個人情報というオブジェクトに対して、
  2. 住所を登録するように指示する。
  3. その際のパラメータは相手の住所情報である。

このように、メソッドを実行する際には、 オブジェクトに対してメッセージを送るという考え方をします。

クラスとインスタンス

クラス

オブジェクトを見いだして、 プログラムの中で「これをオブジェクトとしよう」ということになると、 その対象物はどんなデータ (属性) があり、 どんな操作 (メソッド) ができるのかをプログラムとして記述することになります。 このようなオブジェクトの性質をプログラムとして書いた設計図のことを「クラス」と呼びます。

我々は、実体のモノをある特徴によりグループ化し、 そのグループに対して共通的な名前をつけることで、 モノに対する共通の認識を得ています。 このグループのことが「クラス」です。 クラスは、同じ特性を持つオブジェクトの集合に名前をつけたものです。 オブジェクトの特性を抽象化したものとも言えます。

Javaでは、オブジェクトを利用するためには、 まずプログラムの中でクラスを記述し、 次にクラスに属するオブジェクト (インスタンス) を生成します。 このため、クラスはオブジェクトの設計図である と考えられます。 現実世界において設計図からたくさんの製品が作られるように、 クラスという設計図から、 多くのオブジェクトを生成し利用することが可能になります。

インスタンス

インスタンスとは、 クラスから生成されたそのクラスに属するオブジェクトのことです。 このため、オブジェクト指向プログラミングにおいては、 インスタンスとオブジェクトという言葉は同じ意味で使われます。

一般に、クラスを定義しただけでは、そのオブジェクトを利用することはできません。 そのクラスの実体であるインスタンスを生成して、 はじめてオブジェクトとして利用可能になるのです。

Javaによるオブジェクト指向プログラミング

例題: 携帯電話オブジェクト

身近なオブジェクトの例として、携帯電話を考えてみましょう。 携帯電話の属性と操作とはどのようなものでしょうか。

1. 属性

携帯電話オブジェクトに固有の性質としては、大きさ、重さ、色、メモリ容量などの物理的なもの、 さらに電話番号やメールアドレスなどの登録データが考えられます。 これらは携帯電話に共通の属性ですが、その値はオブジェクトごとに異なります。

class MobilePhone {
    String color;
    String phoneNumber;
    String emailAddress;

    ...

}

2. 操作

携帯電話の操作とは、電話をかける、電話に出る、メールを送る、メールを読む、 アドレス帳を参照する、などのユーザによる操作です。 これらは属性ではなくメソッドで表します。

電話をかけるという例で考えてみると、

  1. 自分の携帯電話に対して、
  2. 電話をかけるように指示する。
  3. その際のパラメータは相手の電話番号である。

となります。このメソッド call は次のようになるでしょう。

class MobilePhone {

    ...

    void call(String phoneNumber) {
	// 電話をかける
	System.out.println("calling " + phoneNumber);
    }

    ...

}

これは、自分の携帯電話に「この電話番号に電話をかけてね」とメッセージを送っていると 考えることができます。 このメッセージに対し、電話をかけることができたか、相手の都合でかけられなかったか、 オブジェクトが返答する場合には、戻り値を使います。

class MobilePhone {

    ...

    boolean call(String phoneNumber) {
	// 電話をかける
	System.out.println("calling " + phoneNumber);
	// 問題なくかかったなら...
	return true;
    }

    ...

}

プログラム全体としては以下のようになります。 生成した携帯電話オブジェクトは phone という変数に代入され、 その携帯電話の操作(= メソッドの実行)は phone に対して行われます。

class MobilePhone {
    String color;
    String phoneNumber;
    String emailAddress;

    void setColor(String colorName) {
	color = colorName;
    }
    void setPhoneNumber(String number) {
	phoneNumber = number;
    }
    void setEmailAddress(String address) {
	emailAddress = address;
    }

    boolean call(String phoneNumber) {
	// 電話をかける
	System.out.println("calling " + phoneNumber);
	return true;
    }
}

class MobilePhoneCaller {
    public static void main(String[] args) {
	MobilePhone phone = new MobilePhone();
	// 属性をセット
	phone.setColor("Pink");
	phone.setPhoneNumber("090-0909-0909");
	phone.setEmailAddress("pinky@ezweb.ne.jp");
	// 電話をかける
	phone.call("03-5280-0000");
    }
}

オブジェクト指向のプログラムの特長

クラスからオブジェクトを生成すれば、 同じ性質のオブジェクトをいくつでも生成でき、 何度でも利用することができるようになります。 また、メソッドの実行によって、 複雑な処理を簡単に何度でも実行できるようになります。

オブジェクト指向のメリットはこれだけではありません。

オブジェクトを使うことによって、 モノを中心にプログラムを書くことができ、 プログラムで扱うデータとそれに対する操作を わかりやすく記述することができます。

一般に、大きなプログラムをひとまとめに書くと理解が難しくなります。 人間はある程度以上に複雑なものを、 すべてを一度に理解することは困難なのです。 このような場合の原則は、全体をいくつかの部分に分けて、 それぞれを別々に理解することです。 オブジェクト指向プログラムはプログラムの中で登場するモノに着目し、 プログラムをオブジェクトの単位で分けることができます。 オブジェクト指向は、人間が現実世界で物事を理解する時の考え方に 近い概念であるため、プログラムの理解が容易になるのです。

オブジェクトは他のプログラムとは独立して仕事をします。 オブジェクトを利用する際は、 オブジェクトが所定の仕事をしてくれると信頼して、 いわばブラックボックスとして考えてしまえば良いのです。

カプセル化と情報隠蔽

製品を表す次のようなクラスがあったとします。

class Product {
    String name;
    String id;

    void setNameAndID(String n, String i) {
        name = n;
	id = i;
    }
}

メソッド setNameAndID では、 特別な計算処理を行っているわけではなく、 与えられたデータを属性に登録しているだけです。 これと同じ処理を、 クラスの外側から set〜 を使わずに

Product myPc = new Product();

myPc.name = "TDU ThinkPad X40";
myPc.id ="2371-A85";

と書くこともできたわけです。 しかし、この書き方は勧められるものではありません。 製品名を変更せずに、型番(ID)だけを変更してしまったり、 その逆を行うこともできてしまいます。 これでは、製品と型番が一対一に対応するという原則が崩れてしまいます。

属性を直接操作するのではなく、 必要な操作だけをメソッドとして用意することで、 想定しないような使われ方をして問題が生じることのないように することが可能です。 オブジェクトは、 データとその操作が一体化されたものなのです。 このような概念をカプセル化 (encapslation) と言います。

また、処理を行う際にメソッドを用いることで、 オブジェクトの中にどういう変数があり、 どのような計算が行われているかといった、 オブジェクトの内部構造や処理手順を把握する必要はありません。 知っていれば良いのはメソッドの使い方だけです。 このような概念を情報隠蔽と言います。