【Java基礎】クラスの作り方

# はじめに
最近Java基礎の研修を受けました。学生時代にJavaを授業で習って基礎は身につけていたのですが、忘れていた内容もあったので備忘録として書き残してみます。

この記事では、**Javaの基礎的な内容に関してまとめていきます**。
今回は**クラスの作り方**です。

# クラスの構成
クラスは以下の3つで構成されます。
+ **フィールド**：インスタンスのデータを保持する変数
+ **メソッド**：オブジェクトが持つ動作
+ **コンストラクタ**：クラスからインスタンスを生成する時に自動的に呼び出される処理

これらのクラスの構成要素のことを**メンバー**と呼びます。

```java:クラス例
class Person {
    // フィールド
    private String name;
    private int age;
    
    // コンストラクタ
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // メソッド
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
```



## メソッドの宣言
メソッドの宣言は以下のような形式で行います。
```HAML:メソッドの形式
修飾子 戻り値の型 メソッド名（引数リスト） {
    メソッドの内容
}
```

修飾子は先の章で説明します。
戻り値の型には、戻り値を返すメソッドはその型名、返さないメソッドはvoidと記述します。

```java:戻り値あり・なしの例
// 戻り値あり
public String getTitle() {
    String title = "Meet Joe Black";
    return title;  // 宣言した戻り値の型と同じ型のものを返す
}

// 戻り値なし
public void errorMessage() {
    System.out.println("エラーが発生しました。");
    // return;   // このように書いても良い。しかし、普通は書かない。
}
```



## フィールドの宣言
フィールドの宣言は以下のような形式で行います。
```HAML:フィールドの形式
修飾子 型名 フィールド名;
```


フィールドには初期値を代入できます。初期値はインスタンスを生成する時に代入されます。
初期値を代入しなかった場合、型に応じたデフォルト値が代入されます。
* 参照型：null
* 基本データ型
  * 数値（intやdoubleなど）：0
  * 真偽値(boolean)：false 

```java:フィールド宣言例
class Person {
    private String name = "Joe";
    private int age;              // デフォルトで0が代入される

    /*省略*/
}
```

### フィールドとローカル変数
フィールドを参照するには、フィールド名をそのまま記述します。変数を参照するときと同じです。

変数はフィールドとローカル変数に分けられます。ローカル変数は、メソッド内で宣言される変数で、**そのメソッド内でのみ参照**できます。一方フィールドは**そのクラス内のすべてのメソッドやコンストラクタの中で参照**できます。


```java:フィールドを参照する
class Person {
    private String name;
    private int age; 
    
    public String getMessage() {
        // ローカル変数messageを宣言する
        // nameとageはフィールドを参照する
        String message = "名前は" + name + "です。年齢は" + age + "歳です。";
        return message;
    }

    public void printMessage() {
        // getMessagem内のローカル変数は参照できない
        // System.out.println(messsage);  // コンパイルエラー
        String message = getMessage();
        System.out.println(messsage);
    }

    /*省略*/
}
```



## コンストラクタの宣言
コンストラクタの宣言は以下のような形式で行います。
```HAML:コンストラクタの形式
修飾子 クラス名（引数リスト） {
    コンストラクタの内容
}
```

メソッドと似ていますが、以下のような違いがあります。
* 戻り値の型は指定しない(voidも記述しない）
* メソッドの代わりにクラス名を記述する
* 引数リストの定義は、メソッドの時と同じ

コンストラクタには、インスタンスを生成すると同時に実行したい処理を記述します。よくあるのが、**フィールドに初期値を代入する**処理です。

```java:コンストラクタの例
class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /*省略*/
}
```

### thisの活用
コンストラクタの例で`this`という単語が出てきました。これは、**ローカル変数とフィールドを区別する**ために使います。
* this付き：フィールド
* thisなし：ローカル変数

名前で区別できる場合は、フィールドにthisをつける必要はありません。

### デフォルトコンストラクタ
自分でコンストラクタを宣言しない場合は、暗黙的に引数なしのコンストラクタが定義されます。これを**デフォルトコンストラクタ**と呼びます。

```java:コンストラクタを定義しない
class Person {

}
```

```java:コンストラクタを定義する
class Person {
    public Person() {
    
    }
}
```

上記2つの例は同じ意味です。



# アクセス修飾子
**アクセス修飾子**は、**メンバーの参照可能な範囲**を表します。
| アクセス修飾子 | 参照可能な範囲 |
|:-|:-|
| public  | すべてのクラスからアクセスできる  |
| private  | 自分のクラスからだけアクセスできる  |
| protected  | 自分のクラスとサブクラスからアクセスできる  |
| 指定なし（package private)  | 自分のクラスと同じパッケージのクラスからアクセスできる  |

アクセス修飾子を利用することで、フィールドに想定外の値が代入されるなどの状態を防ぐことができます。



## カプセル化
**カプセル化**とは、フィールドを直接参照させずに、操作のためのメソッドを用意する手法のことを言います。

以下がカプセル化のポイントになります。
* フィールドは`private`
* フィールドを参照・代入する用のメソッドを別に用意する
* メソッド・コンストラクタの可視性
    * 他のクラスに公開する：`public`
    * 他のクラスに公開しない：`private`



```java:カプセル化したクラスの例
class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        if (age >= 0) {
            this.age = age;
        }
    }

    // nameに値を代入するメソッド
    public void setName(String name) {
        this.name = name;
    }

    // nameの値を取得するメソッド
    public String getName() {
        return name;
    }

    // ageに値を代入するメソッド
    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        }
    }    

    // ageの値を取得するメソッド
    public int getAge() {
        return age;
    }

    // このクラス内でしか参照できない、privateメソッド
    private String getMessage() {
        return "名前は" + name + "です。年齢は" + age + "歳です。";
    }

    // privateメソッドを呼び出して利用するpublicメソッド
    public void printMessage() {
        String message = getMessage();
        System.out.println(message);
    }
}
```




# まとめ
クラスはjavaの基本になります。クラスを上手に定義し、利用していくことでjavaのうまみを活かしていきましょう。