クラス、インスタンス、オブジェクト、コンストラクタ



![スクリーンショット 2024-02-10 10.23.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/4a5458c6-0f71-44d9-c2cc-6b8373dae215.png)

* クラス(設計図)を呼び出して、インスタンス化(オブジェクトを作る)する。
* インスタンス＝オブジェクト

## クラスの定義方法
```java
アクセス修飾子 class クラス名 {
    クラスの中身
}
```
アクセス修飾子 :
`public`　`private`の2種類。

クラス名：
クラス名は**先頭を大文字**にするのが慣例。
(ちなみに、変数はキャメルケース。`static fainal`の定数は全て大文字)

例）商品を扱うクラスを定義する場合
```java
//商品クラス
public class Product{
```

## フィールド
変数と同じ。
1. 宣言
1. 代入
1. 参照

##### 1.宣言と2.代入
* クラスのフィールドでは多くの場合、アクセス修飾子は省略せずに書く
* privateを指定することが多い
* フィールドの宣言は、クラス定義の最初にまとめて書く
```java
アクセス修飾子 データ型 フィールド名;
アクセス修飾子 データ型 フィールド名 = 初期値; // 初期化あり
```
例えば先ほどのクラス定義の続きに、フィールドの宣言を行う場合。
```java
public class Product {  // クラスの定義
    // 以下フィールドの宣言
    private String name  = ""; // 商品名
    private int    price = 0; // 価格
    private int    stock = 0; // 在庫数
    private satatic final String CATEGORY = "日用品" // 商品カテゴリ
```
定数も宣言できる。

##### 3.参照
クラス外：
アクセス修飾子を`public`にしていたらクラスの外からでも参照できます。後で実際に試してみます。
```java
インスタンス名.フィールド名
 ```

 クラス内：
 フィールド名を書くだけで参照できる。
 ※フィールド名には**極力thisを付ける。**
 例えばProductの価格を参照したければ
 ```　java
System.out.println(this price);
 ```
 
 
##### インスタンス化
クラスからオブジェクト(インスタンス)を作成する。
つまりフィールド
```java
クラス名 インスタンス名 = new クラス名( データ1, データ2,・・・ );
```
(new演算子は配列の箱を作成する際にも使用)


ここまででクラス`Public`のフィールドを`Product.java`ファイルにて定義してきました。下記イメージ図の黄色部分。
![スクリーンショット 2024-02-10 11.25.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/7a6d1f3f-1884-44a1-817a-5a90e52a7f08.png)
次は、機能や動作にあたるメソッドの定義。このクラス`Public`でいうと「注文を受けて在庫を更新する機能」に当たります。

## メソッド
メソッドはそのクラスの中においての処理をひとまとめにしたもの。このメソッドを必要なときに呼び出すことで、一連の処理をいつでも実行できる。
* 例　このクラス`Public`に注文を受けて在庫を更新する処理ができるメソッド`takeOrder`を定義する。
イメージ図
![スクリーンショット 2024-02-10 11.49.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/ece49052-abdf-e923-66c6-d380c88e13f5.png)

先ほどのフィールドの定義の続きにメソッド`takeOrder`を追記。
```java
public class Product {
	// フィールド
	private String name  = ""; // 商品名
    private int    price = 0;  // 価格
    private int    stock = 0;  // 在庫数
    private static final String CATEGORY = "日用品"; // 商品カテゴリー

//下記からメソッドのコードーーーーー追記↓ーーーーーーー
//【メソッド】注文を受けて在庫数を更新する 
// number：注文数
public void takeOrder( final int number ) {
    System.out.println("【注文処理開始】");
    System.out.println("商品名：" + this.name );
    System.out.println("単品価格：" + this.price + "円（税込）" );
    System.out.println("注文数：" + number +
                       "／在庫数：" + this.stock );

    // 注文数が在庫数を超えていたら購入不可
    if( this.stock < number ) {
        System.out.println( this.name + "は在庫不足です" );
        return; // 購入できないため終了
    }

    // 購入金額を計算
    int total = this.price * number;
    System.out.println( number + "点で合計" +
                        total + "円（税込）です");

    // 購入のため在庫数を更新
    this.stock -= number;
    System.out.println( this.name + "の残り在庫は" + this.stock );
}
}
```
##### メソッドの呼び出し方
* 生成したインスタンス名にドット（.）を付けて、メソッド名を書く。
* 引数がある場合は()内に記載。
* 事前にインスタンス(オブジェクト。今回の例でいうと商品。)を作成しないといけない。

例）商品：tissueを生成し、注文が3個あった場合

インスタンス化の書き方
`クラス名 インスタンス名 = new クラス名( データ1, データ2,・・・ );`

```Java
// インスタンス(商品)を生成
Product tissue　= new Product("ティッシュ",500,10,"日用品")

// ティッシュを3点注文
tissue.takeOrder(3);
```
これで、商品名ティッシュ、価格500円、在庫10こ、カテゴリが日用品の商品管理ができるようになって、さらにメソッド`takeOrder`を呼び出している。

## コンストラクタ
コンストラクタとは、その初期化処理を行うメソッド。
インスタンス(オブジェクト)の生成時に自動実行される。
クラスをnewした瞬間に実行される関数のこと。
コンストラクタの定義方法は以下の通りで、通常のメソッドとの違いは、
1. 戻り値の型がない
1. クラス名がメソッド名になる

```java
アクセス修飾子 クラス名( 引数1の宣言, 引数2の宣言,・・・) {
    初期化処理;
}
 ```
 例）クラス`Product`のコンストラクタは下記のように定義してみる。
 * 引数で商品名・価格・在庫数を渡し、各フィールドに代入することで初期化。
 * ほかのクラスでインスタンスを生成したいときは、`public`を付ける。
 ```java
 public Product(String name, int price ,int stock ,final String CATEGORY )
        this.name  = name;
        this.price = price;
        this.stock = stock;

        System.out.println("【商品データ生成】" + this.name );
        System.out.println("価格：" + this.price +
                           "円（税込）／在庫数：" + this.stock );
    }
```
例えば、以下のインスタンスを作成したとき、
```Java
// インスタンスの作成
Product tissue = new Product("ティッシュ",500,10,"日用品");
```
ティッシュ、500円、在庫10こ、日用品という情報をコンストラクタに渡していることになる。

## 実際にソースコードを試してみる
![スクリーンショット 2024-02-10 18.28.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/36f15fc3-82b9-de4f-a650-aa1469bc8849.png)

![スクリーンショット 2024-02-10 18.41.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/43447258-a8b6-1c9a-5047-695bb327e8de.png)
![スクリーンショット 2024-02-10 19.37.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/05fd3200-8544-2c50-6f30-6a7dffc5b182.png)
実行結果
```java
【商品データ生成】コーヒー
価格：1000円／在庫数：10
【商品データ生成】フィルター
価格：500円／在庫数：30
【注文処理開始】
商品名：コーヒー
単品価格：1000円
注文数：3／在庫数：10
3点で合計3000円です
コーヒーの残り在庫は7
【注文処理開始】
商品名：フィルター
単品価格：500円
注文数：1／在庫数：30
1点で合計500円です
フィルターの残り在庫は29
【注文処理開始】
商品名：コーヒー
単品価格：1000円
注文数：10／在庫数：7
コーヒーは在庫不足です
```
最初の4行、【商品データ生成】の部分はコンストラクタにおける商品データ生成のメッセージが出力されている。
それ以降は全て`tekeOrder`メソッドの一連の処理による出力。

## まとめ
![スクリーンショット 2024-02-10 20.01.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/332c83d6-fdd3-0dea-672b-d2b23fc66caf.png)

同じパッケージ内で2つのファイルを作る。片方ではクラスを定義したコードのみ記述し、もう片方は`main`メソッドを記述しクラスとメソッドを呼び出してオブジェクトを生成する。
使い回すテンプレートを記述したファイルを作っておき、変動する商品(オブジェクト)登録や在庫管理は別のファイルで記述して、必要に応じてテンプレートを呼び出して使うイメージ。

感想　なんとか概念は整理できたけれど、難しい！概念の理解だけでかなりきついのにコード書くことなんてできるのか。他の言語みたいに、実際触ってみたら雰囲気掴んで大体書けるようになってきた！ってノリは通じなさそうなので、コツコツ、1つずつ時間をかけて理解していかないと後々大変なことになりそう。頑張るぞ〜