Java入門1 似たものをまとめる

前提としてjava,eclipse(または)を動かせる環境であると仮定します。

###System.out.println
今回知り合いに向けてjava入門用のものを書こうと思ったのですが、ただ文法を写経するのも面白くないかなと思いRPGの戦闘ができるプログラミングを何回かに分けて作っていこうと思います。今回はたらたらと文法の説明が続きますが、もしよければ見ていただければ嬉しいです。
まずは手始めに以下を実行してみてください。

```Battle.java
public class Battle {
	public static void main(String[] args) {
		System.out.println("GameStart!");
	}
}
```

コンソールにGameStart!の文字が表示されたと思います。他の文法は気にしなくても今はまだ気にしなくても大丈夫ですがclassの後のBattleとファイル名のBattle.javaこの二つのBattleというのは一致させないといけません。
###変数
では次に少し増やしてみましょう。

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		String name="taro";
		System.out.println(name);
		int hp =10;
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
}

```

いくつか新しいものが増えましたね。
`String name="taro"`というものと`int hp=10`というものが増えたと思います。ここでStringというのは文字列を表しておりintというのは整数を表しています。つまり、文字列のnameという箱に"taro"を入れる、というのと整数のhpという箱に10を入れるというのを表しています。これらも`System.out.println`の中に入れることによってコンソール出力させることが可能です。最後の行に変数と文字列が混ざっていますが、`変数+"文字列"`とすることでもコンソールに出力させることが可能です。
ではもう少し手を加えてみましょう

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		String playerName="taro";
		System.out.println(playerName);
		int playerHp =10;
		System.out.println(playerHp);
		System.out.println(playerName+"のHPは"+playerHp+"です");
		String monsterName = "slime";
		System.out.println(monsterName);
		int monsterHp = 3;
		System.out.println(monsterHp);
		System.out.println(monsterName+"のHPは"+monsterHp+"です");
	}
}
```

色々と変化はありますが、まずname,hpをplayerName,playerHpに変えました。さらにmonsterName,monsterHpを加えました。コピペすれば一瞬ではあるんですがもし自力で書くとしたら面倒だと思いません？なので昔の頭のいい人は考えました。似たものは一緒にまとめてしまおう、と。ここであなたは上のコードから似たものを発見できますか？実は似たものはいくつかあります。

まず、おそらく一番わかりやすいのが
`System.out.println(playerName+"のHPは"+playerHp+"です")`
と
`System.out.println(monsterName+"のHPは"+monsterHp+"です")`の二つです。
他にも名前やHPのみを表示しているところも似ていますね。
これらは以下のようにしてまとめることができます。
###メソッド
```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		String playerName="taro";
		int playerHp =10;
		display(playerName,playerHp);
		
		String monsterName = "slime";
		int monsterHp = 3;
		display(monsterName,monsterHp);
	}
	
	public static void display(String name,int hp) {
		System.out.println(name);
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
}
```

Battle.javaの上に書いてあるものはだいぶすっきりしましたが、新しくdisplayというものが増えました。これはメソッドと呼ばれており動作をまとめるためのものとなります。今回はStringタイプのnameという箱とintタイプのhpという箱が入るのを期待しnameとhpが入ったらそれらを表示してくれる。ということをこのdisplayはしてくれます。メソッドについてもう少し掘り下げてみましょう。
以下を実行してみてください。

```Clac.java
public class Calc {

	public static void main(String[] args) {
		int number1 = 3;
		int number2 = 6;
		int output=plus(number1,number2);
		System.out.println(output);
	}
	
	public static int plus(int plus1,int plus2) {
		int result = plus1+plus2;
		return result;
	}
}
```

ここにもplusメソッドがありますね。これはnumber1とnumber2を足して結果を返してくれるというメソッドです。結果を返すためにまずメソッドで何を返すのかを明示してあげなくてはいけません。それがplusの前にあるintのことです。ここは返す結果のタイプ、つまり型を明示します。そして結果を返すという部分が`return result`の部分になります。staticというが先ほどもついていましたが、これはmainにstaticがついているからつけているのです。あまり重要ではないので今は頭の片隅にでも置いといてください。
では本題に戻りましょうか。
先ほどのBattle.javaですが似たものはまだまだあります。

###クラス
```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player();
		player.name="taro";
		player.hp=10;
		display(player.name,player.hp);
		
		String monsterName = "slime";
		int monsterHp = 3;
		display(monsterName,monsterHp);
	}
	
	public static void display(String name,int hp) {
		System.out.println(name);
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
	
	
}

class Player{
	String name;
	int hp;
}
```
上では新しくPlayerというclassが追加されたと思います。classというのは新しくString,intのような型を自分で作るための機能で、`Player player`は新しくプレイヤーという変数を宣言し、`new Player()`で新しくPlayer型の実体を作り出します。正式名称だとオブジェクトとか言ったりします。コードの行数自体は減っていませんが見やすくなっていますね。先ほどはモンスターのname,hpを入れるために変数の名前を変える必要がありましたがこうしてまとめておけば変数の名前を変えずに済みます。ついでにモンスターの方も作っておきましょう。

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player();
		player.name="taro";
		player.hp=10;
		display(player.name,player.hp);
		
		Monster monster = new Monster();
		monster.name = "slime";
		monster.hp = 3;
		display(monster.name,monster.hp);
	}
	
	public static void display(String name,int hp) {
		System.out.println(name);
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
	
	
}

class Player{
	String name;
	int hp;
}

class Monster{
	String name;
	int hp;
}
```

大分すっきりしましたね。実はここで一つ問題があります。Javaを扱っている人に`player.name`とかいうコードを見られるとしこたま怒られることです。建前としては`player.name`とか直接できるようにすると間違えて値を書き換えてしまうかもしれない、ということです。まぁ怒られるのも嫌なのでメソッドで値の取得、値の代入をするようにしましょう。

###カプセル化
```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player();
		player.setName("taro");
		player.setHp(10);
		display(player.getName(),player.getHp());
		
		Monster monster = new Monster();
		monster.setName("slime");
		monster.setHp(3);
		display(monster.getName(),monster.getHp());
	}
	
	public static void display(String name,int hp) {
		System.out.println(name);
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
	
	
}

class Player{
	private String name;
	private int hp;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

class Monster{
	private String name;
	private int hp;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}
```

privateというのはアクセスを制限するためのもので同じクラスから以外はアクセスできないようになります。またsetNameやsetHpなどのなかに使われているthisというキーワードはこのクラスの、という意味です。これによってメソッドでもらう値も同じnameでいいので分かりやすくなります。
ここでさらに似たものがあります。それはPlayerとMonsterですね。これらをまとめてみましょう。

###継承

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player();
		player.setName("taro");
		player.setHp(10);
		display(player.getName(),player.getHp());
		
		Monster monster = new Monster();
		monster.setName("slime");
		monster.setHp(3);
		display(monster.getName(),monster.getHp());
	}
	
	public static void display(String name,int hp) {
		System.out.println(name);
		System.out.println(hp);
		System.out.println(name+"のHPは"+hp+"です");
	}
	
	
}

class Animal{
	private String name;
	private int hp;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

class Player extends Animal{
	
}

class Monster extends Animal{
	
}

```

新しくAnimalクラスができて、PlayerとMonsterは`extends Animal`というのがついてると思います。これは継承というもので値、メソッドをそのまま受け継いでくれます。なので、PlayerやMonsterなどから値、メソッドが消え去っても上の方でエラーは起こりません。また継承を行うとこんなこともできます。
###ポリモーフィズム

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player();
		player.setName("taro");
		player.setHp(10);
		display(player);
		
		Monster monster = new Monster();
		monster.setName("slime");
		monster.setHp(3);
		display(monster);
	}
	
	public static void display(Animal animal) {
		System.out.println(animal.getName());
		System.out.println(animal.getHp());
		System.out.println(animal.getName()+"のHPは"+animal.getHp()+"です");
	}
	
	
}

class Animal{
	private String name;
	private int hp;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

class Player extends Animal{
	
}

class Monster extends Animal{
	
}

```

displayメソッドを書き換えて`display(Animal animal)`としました。そこに`display(player)`とか`display(monster)`のように直接入れています。型が違うのでエラーが起こるように思えますが、継承によってPlayerやMonsterはAnimalという型を受け継いでいるので問題ありません。
さらに以下の機能を使うことでさらに簡単にできます。
###コンストラクタ

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player("taro",10);
		display(player);
		
		Monster monster = new Monster("slime",3);
		display(monster);
	}
	
	public static void display(Animal animal) {
		System.out.println(animal.getName());
		System.out.println(animal.getHp());
		System.out.println(animal.getName()+"のHPは"+animal.getHp()+"です");
	}
	
	
}

class Animal{
	private String name;
	private int hp;
	
	public Animal(String name,int hp){
		this.name=name;
		this.hp=hp;
	}
	
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

class Player extends Animal{
	public Player(String name, int hp) {
		super(name, hp);
	}
}

class Monster extends Animal{
	public Monster(String name, int hp) {
		super(name, hp);
	}
	
}

```

Animalの中にAnimalと書かれたものが新しく追加されました。これはメソッドではなくコンストラクタといって、newで新しくオブジェクトを作るときに値をセットすることができます。メソッドではないのでpublicの後に型がありません。また、コンストラクタは継承することができないのでPlayer,Monsterにもコンストラクタを作っています。thisで値をセットすることができないので、super()というものを使って値を入れています。
これで最高にシンプルになりましたが、継承というもの自体実は扱いが難しくあまり使うのはおすすめできません。理由としては変化に弱くなる、ということがあげられます。Javaの継承自体一つのクラスしか継承することができません。複数を継承したいといった場合Aを継承したB,Bを継承したC,Cを継承したクラスということになりますが、他にもAを継承したB,Bを継承したD,Dを継承したクラスがあったとして、このときA,Bをどちらか一方のクラスの実装に合わせるともう一方のクラスではエラーが起きてしまうかもしれません。エラーを直せるにしてもコードが汚くなってしまう可能性は高いでしょう。なので継承を使うことはおすすめしません。
一方で`display(Animal animal)`にMonster型やらPlayer型を入れたい(いわゆるポリモーフィズムといいます)という気持ちはあるので代わりにインターフェイスというものを使いましょう。
###インターフェイス

```Battle.java
public class Battle {
	public static void main(String[] args){
		System.out.println("GameStart!");
		Player player=new Player("taro",10);
		display(player);
		
		Monster monster = new Monster("slime",3);
		display(monster);
	}
	
	public static void display(Animal animal) {
		System.out.println(animal.getName());
		System.out.println(animal.getHp());
		System.out.println(animal.getName()+"のHPは"+animal.getHp()+"です");
	}
	
	
}

interface Animal{
	String getName();
	int getHp();
}

class Player implements Animal{
	private String name;
	private int hp;
	
	public Player(String name,int hp) {
		this.name=name;
		this.hp=hp;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

class Monster implements Animal{
	private String name;
	private int hp;
	
	public Monster(String name,int hp) {
		this.name=name;
		this.hp=hp;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHp() {
		return hp;
	}
	public void setHp(int hp) {
		this.hp = hp;
	}
}

```

継承関連を一旦消して、新しくinterfaceというものとPlayerとMonsterにimplementsというものをしていますね。しかし、mainの中のコードはそのままになっています。これは、extendsと同じでAnimalというクラスも持っているので上記のコードでも大丈夫なのです。interfaceの中に`String getName()`と`int getHp()`がありますがこれをやっているおかげでmainのdisplayでもgetName()やgetHp()などを使うことができます。また、インターフェースの特徴としてimplementsした場合interfaceに書かれているものは必ず書かなければなりません。今回はgetName()とgetHp()が書かれてるのでこれらは必ず書かないと文法エラーになります。しかし逆に文法エラーを起こしてくれることによって、implementsしたものは必ずgetName()とgetHp()を動作してくれることを保証してくれます。
継承とインターフェースの違いですが、私自身曖昧です。曖昧ですが説明しますと継承はめっちゃ結びつく、インターフェースはゆるーく結びつく、みたいなことかなと思っています。

以上で今回は終わりです。
ここまで長々と説明させていただきましたが、いかがだったでしょうか。少しでも参考になれば幸いです。