Javaのクラスとインスタンス(オブジェクト指向)

##  クラスの宣言
クラスは簡単に言えば「これからプログラム処理を開始します」と**宣言**すること。
どんなプログラムを開始するのか、その種類を宣言するためにクラスを用いる。
Javaのクラスは設計図によく例えられる。
例えば、家であれば「人が住む」、車であれば「人を乗せて走る」ことをコンセプトに、設計図が作られ、Javaのクラスも同様に「Javaに何をさせるのか」を、クラスの中に記述していく。

## Javaのプログラムの構成はクラスの集まり
Javaのプログラムは**クラス**の集まり。

Javaのクラスは２種類ある
①mainメソッドを記述すし、プログラムを実行するための**実行用クラス**
```:実行用クラス
　class クラス名{
     　 public static void main(String args[]) {
		　　:　　　　　　　　　　　　　　　　　　　 ↑mainメソッド
         :
	}
}
```
②クラスが持つ属性（変数、情報、データなど）と操作（メソッド、機能、処理、命令文など）を記述する**設計図クラス**
```:設計図クラス
　class クラス名{
     　 変数（フィールド）の定義　　←クラスが持つ情報（値を格納するための変数）を記述
　　　　　　　　　　　　　　　　　　　　：
　　　　　　　　　　　　　メソッドの定義　←クラスが持つ機能（命令文のまとまり）を記述
　　　　　　　　　　　　　　　　　　　　：
}
```
![スクリーンショット 2022-11-02 11.36.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/ea9b1b42-676c-90c6-7fce-a9552f9406df.png)
上の写真はクラス名を生徒クラスとした設計図クラス。
この写真の例としては生徒クラスは名前と英語の点数、数学の点数の属性（データ）と点数を表示する操作（処理）を持っている。
属性と操作という呼び方はオブジェクト指向の考え方の呼び方でプログラミングの単語に言い換えるとそれぞれ**属性→変数**、**操作→メソッド**となる。

クラスが持つ属性として定義する変数のことをメソッドの中の変数と区別をつける為に**メンバ変数**と呼ぶ。
またメンバ変数と似た様な構文でクラスの特性を表す**フィールド**と言う変数がある。その構文は、変数の定義とほぼ同じだが、先頭に修飾子を付与できる点が異なりフィールドはクラス内のメソッドから参照可能な変数になる。

フィールドの宜言とメソッドの宣言は、どちらか一方しかなくてもOK。

```:例文(フィールドのみ宣言)
class Point{　←Pointという名前のクラスを宣言
	int x;　←xとyという名前のフィールドを宣言
	int y;　　　　　（intはデータ型の名前でxとyがフィールド名になる）
}
```



## クラスを作る際のルール
・クラス名とファイル名は同じにする。
・クラスの内容を "{" から "}"の間(**ブロック**)に書く。
・一つ一つの処理分は最後に**セミコロン**(;)で終わる。
・Javaではプログラムを実行する時は一番最初に**mainメソッド**から実行される。
・設計図クラスではクラス名の直下に変数の定義をして、その後にメソッドを定義する。

```:サンプルプログラム
class Student{
  //変数（属性）
  String name;
  int engScore;
  int mathScore;

  //メソッド（操作）
  void display(){
    System.out.println(name + "さん");
    System.out.println("英語" + engScore + "点・数学" + mathScore + "点");
  }
  void setScore(int eng, int math){
    engScore = eng;
    mathScore = math;
  }  
  double getAvg(){
    double avg = (engScore + mathScore) / 2.0;
    return avg;
  }
}
```

Javaでは、一つのファイルに一つのクラスを記述した上で、ファイル名は「クラス名.java」にするというルールがある。ファイル名と異なるクラスを使う場合、特に同一パッケージ(ファイル)内で同名のクラスがあると名前の衝突が起こる可能性があるので注意する。  

### 修飾子のあるクラス
```
[装飾子]　　class クラス名{
     　変数の定義
　　　　　　　　　　　　　　　　　　　　：
　　　　　　　　　　　メソッドの定義
　　　　　　　　　　　　　　　　　　　　：
}
```
修飾子とは、クラスやインターフェイス（クラスがどのようなメソッドを持っているのかをあらかじめ定義する、いわば設計書のような存在）、また、そのメンバーの性質を決めるキーワードで、それぞれの宣言の先頭に付与できる。



## インスタンス
・インスタンスとはクラスを元に作られる**オブジェクト**のことを指し「実体」と表現されることもある。
「オブジェクト」という言葉には、「モノ」という意味があり、後述するオブジェクト指向プログラミングでは、プログラムの機能や役割を区別し、それぞれを部品（オブジェクト）として組み合わせることで1つのプログラムを作る。
![スクリーンショット 2023-01-30 17.28.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/489c4fd1-b11a-5d91-123e-577446099830.png)
＊クラスから生成された個々のオブジェクトを特にインスタンスと呼ぶ。つまりインスタンスもオブジェクトの言葉のうちの一つ。

```:基本構文
クラス名　変数名（オブジェクト名）　＝　new　クラス名（）;
```
次のように記述することで、Pointクラスのオグジェクト名pを生成する事ができる。
```:例文
Point p = new Point();
```
このように、インスタンスを代入する変数の型には、そのクラス名（ここではPoint) を指定する。pはPoint型の変数となる。
この変数pに代入されたインスタンスが持つ変数xとyには、次のようにして値を代入できる(xに10を、yに5を代入している）
```
p.x = 10;
p.y = 5;
```
Pointクラスに定義されている変数xとyは、インスタンスに情報を格納するために使用できる。
これらを**インスタンス変数**と呼ぶ。
インスタンス変数を参照するときには「p.x」のように、「インスタンスを代入した変数の名前 ＋ ドット（.）＋インスタンス変数の名前」という形で記述する。

### クラスとインスタンスを使ってプログラムを作成
プログラム内容は点xと点yの座標を表すプログラム
```:PointInstanceExample.java
class Point{
	int x;
	int y;
}

class PointInstanceExample {
	public static void main(String[] args) {
		
		Point p1 = new Point();
		p1.x = 10;
		p1.y = 5;

		Point p2 = new Point();
		p2.x = 5;
		p2.y = 2;
		
		System.out.println("p1のx座標は" + p1.x);
		System.out.println("p1のy座標は" + p1.y);
		System.out.println("p2のx座標は" + p2.x);
		System.out.println("p2のy座標は" + p2.y);
    }
 }
```
### インスタンスの配列化
宣言した配列にいくら値を詰めるのか、領域の確保をしてあげなければいけない。
配列インスタンスの生成の際には
・配列インスタンスの生成には必ず要素数を指定すること。
・多次元配列の場合は、変数の次元数と参照先の次元数が一致すること。
を気を付ける。

new [要素数]での確保する領域の大きさ決める。
```
Point[] points = new Point[5];
```
これで、Pointクラスのインスタンスヘの参照を格納できる要素（入れ物）が5つ確保した。
一つずつ記述すると以下になる。
```
points[0] = new Point();
points[1] = new Point();
points[2] = new Point();
points[3] = new Point();
points[4] = new Point();
```

以下は具体的な例として、points[i] (インデックスがiで指定されるPoint クラスのインスタンス）に、x = i, y = i * i の座標を設定するプログラムコード。
```
class Point{
	int x;
	int y;
}

class Array {
	public static void main(String[] args) {
		Point[] points = new Point[5];
		for(int i = 0; i < 5; i++){
			points[i] = new Point();
			points[i].x = i;
			points[i].y = i*i;
		}
		for(int i = 0; i < 5; i++ ) {
			System.out.println("points[" + i + "]の座標は(" + points[i].x + " ," + points[i].y +")");
		}
    }
 }
```
Point[] points = new Point[5];で配列を宣言。
for(int i = 0; i < 5; i++){でiが0~4の間ループさせる。
points[i] = new Point();で新しいインスタンスを作成し、xとyの値を設定する。

```:出力結果
points[0]の座標は(0 ,0)
points[1]の座標は(1 ,1)
points[2]の座標は(2 ,4)
points[3]の座標は(3 ,9)
points[4]の座標は(4 ,16)
```
14,15行目で各インスタンスの値を繰り返し出力させる。

このように5つのインスタンスの参照が配列に格納され、それぞれのインスタンスには異なる座標値を設定できた。
複数のインスタンスを管理するのに配列を使用できる。

## オブジェクト指向
オブジェクト（インスタンス）を中心にしてプログラムを作る考え方の事を**オブジェクト指向**と呼ぶ
![スクリーンショット 2023-01-30 17.32.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/78601ec0-441c-3286-01b5-1f35b5587db0.png)
上の写真のように「生徒の情報を持ったクラス」、「出席情報を持ったクラス」、「それぞれまとめた情報を呼び出して利用する実行用クラス」といったように持っているデータや処理を切り分けてクラスを組み合わせて動かしていくのがオブジェクト指向の考え方になる。

**オブジェクト指向のメリットは大きく分けて以下の3つになる。**
・プログラムを効率よく作ることができる
・不具合が起きたときに対処しやすい
・プログラムに変更を加えやすい


## まとめ
**・クラスはインスタンスを作るための設計図でオブジェクトが持つ情報と機能を定義するもの。**
オブジェクト指向言語では、プログラム部品であるオブジェクトを組み合わせて1つのプログラムを完成させる。
Java言語でプログラミングするということは、クラスを宣言すること。
Java言語のプログラムは1 つ以上のクラスから構成される
クラスには、フィールドとメソッドが含まれる


**・インスタンスはクラスから作られた実体である。**
クラスに基づいて作られるオブジェクトを「インスタンス」と呼ぶ。
1つのクラスからは、インスタンスをいくつでも生成できる。
フィールドにはインスタンス変数と呼ばれる変数を宜言でき、インスタンス名にドット（.）をつけて参照できる。




分かりにくい方は家を作る場合を想像してみてください。この場合、クラスは家を作るための設計図で、インスタンスは設計図から作られた家となります。