オブジェクト指向

オブジェクト指向の考え方

ここではJava言語の特徴である、オブジェクト指向について、詳しく説明します。オブジェクト指向とは、あらゆるものを、すべて「モノ」として表現するという考え方のことを言います。オブジェクト指向の、オブジェクト(Object)とは、英語で「モノ」を表す言葉です。

例えば、自動車を運転する際には、自動車内部の仕組みを理解する必要はありません。ただ運転方法だけを知っていれば、それだけで自動車を使うことができます。

つまり、「自動車」というオブジェクトは、動作させる仕組みがすでに内部に組み込まれていることから、それを利用するためには、仕組みを知る必要は一切なく、ただアクセルを踏む、ハンドルを切るなどといったような適切な操作をすればよいことになります。(図6-1参照)

図6-1.オブジェクト指向の考え方
オブジェクト指向の考え方:車を例に

オブジェクトには、操作にあたる、メソッドと呼ばれる部分と、データにあたるフィールドがあります。自動車の例で言えば、「発進する」「停止する」などがそのメソッドで、フィールドは、スピード、走行距離、といったところでしょう。(表6-1参照)

表6-1:自動車オブジェクトのメソッドとデータ
フィールド スピード
走行距離
排気量
メソッド 発信する
停止する
曲がる

クラスとオブジェクト

以上で、だいたいオブジェクト指向の考え方が理解できたかと思います。そこで、ここではさらに、クラスという概念について説明します。前述の、自動車という例を用いて説明すると、通常、世の中には、自動車がたくさん存在します。

オブジェクトは、こういった、ここの物体をさす場合に用いられる概念で、このほかに、インスタンスという呼び名もあります。

ただ、こういった自動車も、もとはひとつの設計図を元に大量生産されているはずなのです。この、設計図にあたるものを、クラスと言います。つまり、クラスがなければ、オブジェクトもありえないのです。以上が、基本的なオブジェクト指向の考え方です。オブジェクト指向には、このほかに様々な概念がありますが、今後適宜紹介していきます。(図6-2.参照)

図6-2.クラスとオブジェクト
クラスとオブジェクト

サンプルプログラム

配列変数について詳しく説明する前に、まずは以下のプログラムを入力・実行してみてください。

SampleClass01.java
package day6;

public class SampleClass01 {
	//	フィールド
	int n = 10;
	String s = "field";
	//	メソッド
	int add(int a,int b){
		return a + b;
	}
	String add(String s){
		return this.s + s;
	}
	void showNum(){
		System.out.println("n = " + n);
	}
}
Sample601.java
package day6;

public class Sample601 {

	public static void main(String[] args) {
		SampleClass01 s = new SampleClass01();	//	インスタンスの生成
		s.n = 100;			//	フィールドnに値を代入
		s.s = "Hello";		//	フィールドsに値を代入
		int ans = s.add(1,2);			//	メソッドadd()を呼び出し
		String str = s.add("World");	//	メソッドadd()を呼び出し
		System.out.println(ans);		//	呼び出し結果の表示
		System.out.println(str);		//	呼び出し結果の表示
		s.showNum();					//	メソッドshowNum()を呼び出し
	}
}
実行結果
HelloWorld
3
n = 100

今までと違い、ソースコードが複数になりました。SampleClassというクラスのインスタンスを生成し、処理を行っているのが、Sample601.javaです。以下、その詳細を見てみましょう。

インスタンスの生成

すでに述べたとおり、オブジェクト指向の考え方では、クラスから、オブジェクト(インスタンス)を生成し、それを操作するというのがオブジェクト指向の考え方です。Javaでは、「インスタンス」という言葉の使用頻度が高いので、そちらを用いることにしましょう。

Javaでは、クラスの宣言は、classというキーワードが用いられます。そのクラスのインスタンスを生成しているのが、Sample601.javaの6行目です。

インスタンスの生成
SampleClass01 s = new SampleClass01(); // インスタンスの生成

これにより、変数sは、SampleClass01のインスタンスになります。

フィールド

クラス、SampleClass01には、フィールドメソッドが存在します。まずは、フィールドから説明しましょう。SampleClass01クラスには、以下のフィールドが存在します。(表6-2.)

表6-2.SampleClass01のフィールド
フィールドの名 初期値
n int 100
s String "World"

フィールドには、初期値を代入することが可能です。初期値は、変数の宣言の後に"="をつけて、そのあとに記述されます。(SampleClass01.java、7~8行目)これらの値は、インスタンス生成と同時に代入されます

これにより、インスタンスsは、int型のnという変数と、String型のsという変数を持つことができるようになります。クラスの外部である、Sample601.javaからは、以下のようにアクセスします。(7行目、8行目)

フィールドへの値の代入
s.n = 100;
s.s = "Hello";

これにより、インスタンスsのフィールドnには、100という値が、sには、"Hello"という文字列が代入されます。

メソッド

続いて、操作であるメソッドについて説明しましょう。メソッドとは、他の言語では、関数(かんすう)と呼ばれる処理です。何らかのデータを外部から受け取り、それをもとに処理をして、実行結果を出力するというものです。例えば、SampleClass01.javaの8行目から10行目を見てください。

addメソッド①
int add(int a,int b){
    return a + b;
}

()内に出ている、変数a,bを引数(ひきすう)と言います。引数とは、メソッドが処理を行う際に、外部から与えるデータのことです。このメソッドは、int型のデータを2つ必要とするという意味です。続いて、returnというキーワードがありますが、ここに出力する値をアウトプットするためのものです。

つまり、このメソッドは、整数型の引数を2つ受取り、その和を返す処理です。この処理を実際に呼び出しているのが、Sample601.javaの9行目です。引数として、1と2を与えるため、戻り値として、その和である3が返され、画面に出力されます。(図6-3.参照)

図6-3.addメソッドの呼び出しイメージ①(数値)
メソッド呼び出しのイメージ(引数と、戻り値の関係)

メソッドのオーバーロード

続いて、メソッドのオーバーロードについて説明します。SampleClass01には、addメソッドが2つ存在します。11行目から13行目にあるのが、もうひとつのaddメソッドです。

addメソッド②
String add(String s){
    return this.s + s;
}

このように、引数や戻り値が異なる複数のメソッドが存在することを、オーバーロードと言います。

このメソッドでは、引数として、String型の変数s、戻り値として、String型をとっています。しかし、この引数「s」は、フィールドのsと名前が重複しています。どううやって区別するのでしょうか?

答えはreturnの部分を見ればわかります。「this.s」が、フィールドのs、何もついていないsが、この引数のsです。thisは、自分自身のインスタンスを表すキーワードであり、「this.」の後に変数名をつけると、フィールドを表します。

そのためSample601.javaの10行目を見るとわかりますが、すでにこの段階でフィールドsには、"Hello"という値が代入されているので(8行目参照)、これに引数sの値が"World"が追加され、"HelloWorld"として出力されます。(図6-4.参照)

図6-4.addメソッドの呼び出しイメージ②(文字列)
メソッド呼び出しのイメージ(引数とフィールド、戻り値の関係)

引数・戻り値のないメソッド

原則として、メソッドには、引数と戻り値がありますが、例外も存在します。つまり、引数のないメソッド、もしくは戻り値のないメソッドが存在します。それが、SampleClass01.javaの14行目~16行目のshowNum()メソッドです。

showNumメソッド
void showNum(){
    System.out.println("n = " + n);
}

戻り値の部分に出ているvoid(ボイド)は、戻り値がないということを表します。そのため、このメソッドは、returnで値を返していません。さらに、()内に、引数がありません。これは、このメソッドに引数がないことを表します。

このメソッドは、引数および戻り値がなく、単にフィールドnの値を表示させるものです。すでにこのメソッドを呼び出される段階では、nには100が代入されているので、「n=100」と表示されます。

ここでは、引数がないので、単にnと書くだけで、フィールドnだとわかりますが、「this.n」と書いても同じ意味です。

複数のインスタンス

サンプルプログラム

クラスのインスタンスは、複数作ることが可能です。以下に、その例を示しますので、入力して実行してみてください。

Sample602.java
package day6;

public class Sample602 {

	public static void main(String[] args) {
		SampleClass01 s1,s2;
		s1 = new SampleClass01();
		s2 = new SampleClass01();
		//	インスタンスs1,s2ごとに、フィールドに違う値を代入
		s1.n = 100;
		s2.n = 200;
		s1.s = "ABC";
		s2.s = "あいう";
		//	インスタンスごとにメソッドを呼び出す。
		System.out.println(s1.add("DEF"));
		System.out.println(s2.add("えお"));
		s1.showNum();
		s2.showNum();
	}
}
実行結果
ABCDEF
あいうえお
n = 100
n = 200

インスタンスごとの実行結果の違い

フィールドs,nは、インスタンスが異なれば、違うものとして扱われます。s1,s2という異なるインスタンスでは、同じフィールドs,nによって、違うものです。メソッドに関しても同様で、同一名のメソッドでも、フィールドが違うと、実行結果が異なります。これが、オブジェクト指向のフィールドおよびメソッドの特徴です。(図6-5.参照)

図6-3.インスタンスとフィールド・メソッドのイメージ
インスタンスとフィールド・メソッドのイメージ

練習問題 : 問題5.