【Java】クラスの使用方法

2018年3月11日

本稿はクラスについて説明していきます。

クラスとは具体的に何なのかというと、オブジェクトを生成するための設計図です。

Javaはこの設計図を基に新しいデータの塊を作成します。

これまでさんざん使用してきた、String型というのもJavaが標準で用意しているクラスなのです。

そして文字列の比較メソッドというのはStringクラスに定義されているメソッドの一つなのですね。

Javaはこのクラスという名の設計図が標準でいくつも用意されていて、そのクラスの中に複数のメソッドが定義されています。

Javaのメソッドを利用するにはクラスの知識も必要で、それらのメソッドを利用して、楽にプログラミングができるのです。

今回はそのクラスを作成する手段を覚え、オブジェクト指向的なプログラミングができるようにしていきたいと思います。

クラスを作成して、利用する

まずは、どのようなクラスを作成するか考えてみましょう。

例えばRPGの魔法使いのキャラクターの一人ひとりに独自のステータスを持たせたい場合、ここまで説明した範囲の知識であればどう定義するでしょうか。

多分こんな感じになると思います。

public class Test{
	public static void main(String[] args){
		String charaName1 = "魔女";
		int hp1 = 100;
		int mp1 = 50;
		
		String charaName2 = "白夜の魔女";
		int hp2 = 200;
		int mp2 = 150;
		
		System.out.println(charaName1+"はhp="+hp1+":mp="+mp1+"です。");
		System.out.println(charaName2+"はhp="+hp2+":mp="+mp2+"です。");
	}
}
実行結果

魔女はhp=100:mp=50です。
白夜の魔女はhp=200:mp=150です。

もちろんこれでも問題ありませんが、ここまで同じような定義がされるような場合は、クラスが使えます。

キャラクターのステータスを表す設計図を作成するとよさそうですね。

設計図の作成方法は

class クラス名{
定義したい変数;
定義したい変数;
定義したい変数;
}

となります。

クラスからデータの実体を作成するには「クラス型 変数 = new クラス型()」と記述します。

実体を作成することをインスタンス化するともいいます。

クラス内の変数にアクセスしたい場合は「クラス変数.変数名」でアクセス可能です。

それでは、実際にクラスを作成して設計図からステータスを生成してみましょう。

public class Test{
	public static void main(String[] args){
		CharaStatus st1 = new CharaStatus();
		st1.name = "魔女";
		st1.hp = 100;
		st1.mp = 50;
		
		CharaStatus st2 = new CharaStatus();
		st2.name = "白夜の魔女";
		st2.hp = 200;
		st2.mp = 150;
		
		System.out.println(st1.name+"はhp="+st1.hp+":mp="+st1.mp+"です。");
		System.out.println(st2.name+"はhp="+st2.hp+":mp="+st2.mp+"です。");
	}
}

class CharaStatus{
	String name;
	int hp;
	int mp;
}
実行結果

魔女はhp=100:mp=50です。
白夜の魔女はhp=200:mp=150です。

なんかコードが長くなったように見えますが、名前、HP、PPがそれぞれ一つのデータとなって扱えるようになるため、無駄にたくさんの変数を宣言しなくてよくなっていますね。

この一つのものに集約できる機能はプログラムの規模がでかくなればなるほど重要になっていきます。

複数のデータを集約して一つの物として考えれば混乱しにくくなりそうだと思いませんか?

ちょっと変な例えかもしれませんが、車は複数のパーツからできて1台の車ができているわけですが、個々のパーツがバラバラになっている状態から何とか運転させようとするのと、全てのパーツが集約された車というものを運転させようとするのとでは、どちらのほうが運転しやすそうですか?

車自体を扱うほうが、運手は簡単そうな気がしないですか?

プログラムでもいろんなパーツが散らばってしまうと訳が分からなくなり、バグを引き起こしやすくなるんですね。だから、できるだけ一つに集約した物体として扱おうというわけです。

イメージ

クラスメソッド

クラス内にメソッドを作成することもできます。

class クラス名{
戻り値 メソッド名(引数){
//任意の処理
}
}
のように記述すると定義できます。

定義したメソッドには、「クラス変数.メソッド名(引数)」でアクセスできます。

実体化したメソッド呼び出し時には実体化しているデータとして内部にアクセスできるため、メソッド実行時の振る舞いを別の実体と変えることができます。

わけがわからないと思うので、実際にメソッドを定義して実行までをやってみましょう。

public class Test{
	public static void main(String[] args){
		CharaStatus chara1 = new CharaStatus();
		chara1.name = "小〇さん";
		chara1.hp = 30;
		chara1.mp = 0;
		
		CharaStatus chara2 = new CharaStatus();
		chara2.name = "トー〇";
		chara2.hp = 75000;
		chara2.mp = 50000;
		
		CharaStatus chara3 = new CharaStatus();
		chara3.name = "カン〇";
		chara3.hp = 20000;
		chara3.mp = 5000;
		
		chara1.printPower();//chara1の戦闘力を表示
		chara2.printPower();//chara2の戦闘力を表示
		chara3.printPower();//chara3の戦闘力を表示
	}
}

//キャラのステータスクラス
class CharaStatus{
	String name;
	int hp;
	int mp;
	void printPower(){
		System.out.println(name+"は"+(hp+mp)+"の戦闘力を持つ。");
	}
}
実行結果

小〇さんは30の戦闘力を持つ。
トー〇は125000の戦闘力を持つ。
カン〇は25000の戦闘力を持つ。

クラスメソッド、printPowerは同じプログラムなのにそれぞれ違う値を表示できています。

それぞれのCharaStatusオブジェクトが、別の変数を持っているということがわかるかと思います。

以前はstaticメソッドを使用しましたが、オブジェクト個々の振る舞いを定義したメソッドを使いたい場合はstaticは付けないようにしましょう。

コンストラクタ

クラスにはコンストラクタと呼ばれる特殊なメソッドが定義できます。

これは「new クラス型(引数)」を呼び出した時に呼び出されます。

任意で引数を指定することもできます。

クラス側の定義は

クラス名(){
//コンストラクタの処理
}
とします。

コンストラクタはオブジェクト作成時にデータを初期化したいときなどに使えます。

それではサンプルをご覧ください。

public class Test{
	public static void main(String[] args){
		Latifa l1 = new Latifa("普通");
		Latifa l2 = new Latifa("赤");
		Latifa l3 = new Latifa("黄色");
		l1.print();
		l2.print();
		l3.print();
	}

}

//ラティファという名前のキャラクタを示すクラス
class Latifa{
	String color;

	//コンストラクタ
	Latifa(String clr){
		color = clr;
	}
	
	void print(){
		System.out.println("私は"+color+"のラティファです。");
	}
}
実行結果

私は普通のラティファです。
私は赤のラティファです。
私は黄色のラティファです。

今回のコンストラクタの場合だとコンストラクタにはどんな特徴かを引数で渡して初期化するようにしました。

設計図からオブジェクトを生成するということがそろそろイメージできて来たのではないでしょうか。

インスタンスイニシャライザ

コンストラクタ以外でも初期化する手段はあります。

それが、インスタンスイニシャライザです。

クラスの内部に{}と記述するだけで定義ができます。

public class Test {
	public static void main(String[] args){
		Latifa latifa = new Latifa();
	}
}
class Latifa{
	{
		System.out.println("インスタンスイニシャライザの呼び出し");
	}
}
実行結果

インスタンスイニシャライザの呼び出し

自身のクラスを明示的に示す

通常メソッド内の変数は同じ名前を付けられませんが、クラスの場合はつけることができます。

ただ、名前が被った場合はメソッドの変数を指定したものが呼び出されるため、クラス変数側を呼び出せません。

クラス側の変数を呼び出す方法も用意されています。

「this.変数名またはメソッド名」と記述することで呼び出すことができます。

public class Test{
	public static void main(String[] args){
		new Latifa("ラティファ");
	}
}

class Latifa{
	String name="にゃあこ"; 
	Latifa(String name){
		System.out.println(this.name);
		System.out.println(name);
	}
}
実行結果

にゃあこ
ラティファ

メソッドのほうはあまり使用しないですが、「this.メソッド名」と明示して実行することもできます。

クラス変数を初期化しなかった場合

クラス変数を初期化しなかった場合は型によって自動で初期化される値が変更されます。

数値なら0、booleanならfalse、クラス系の型はnullです。

public class Test{
	public static void main(String[] args){
		Person p = new Person();
		System.out.println(p.name);
		System.out.println(p.is);
		System.out.println(p.num);
	}
}
class Person{
	String name;
	boolean is;
	int num;
}
実行結果

null
false
0