【Java】オブジェクト指向構文 - コンストラクタ

#コンストラクタ
* クラス利用時に**new演算子でインスタンス化(オブジェクト生成)するタイミングで呼び出されるメソッド**
* フィールドの初期化、クラスで利用する外部リソースの準備の記述に使う
    * **利用できるのはアクセス修飾子**
        * public, protected, private
    * **戻り値なし**
        * 戻り値はvoidではなく**型そのものを記述不可能**
        * return命令も使えない
    * **自由に命名不可**
        * 名前はクラス名と同じにする
* コンストラクタで引数を対応するフィールドにセットする
    * 引数とフィールドは同じ名前に
    * `this.フィールド名=引数;`
    * フィールドの初期化子とコンストラクタが双方あればコンストラクタの初期化が優先

```java
//コンストラクタで引数name/ageを対応するフィールドにセット
public class Person {
  public String name;
  public int age;

  //コンストラクタ
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String show() {
    return String.format("%s（%d歳）です。", this.name, this.age);
  }
}
```

```java:ConstBasic.java
public class ConstBasic {
  public static void main(String[] args) {
    var p = new Person("山田太郎", 30);
    System.out.println(p.show()); //山田太郎（30歳）です。
  }
}
```

##デフォルトコンストラクタ
* 定義省略時に**暗黙的に生成してくれる引数のない空のコンストラクタのこと**
* 以下は同じ
    * 引数付きのコンストラクタを追加した時にエラーになってしまうので注意

```java
public class MyClass{
}
```
```java
public class MyClass{
    public MyClass(){
    }
}
```

##オーバーロード
*　コンストラクタは複数のシグニチャを持てる    
    *　StringBuilder()　
    *　StringBuilder(String str):文字列でStringBuilderオブジェクト生成
    *　StringBuilder(int capacity):文字列、容量でStringBuilderオブジェクト生成
*　thisを使って引数の一致するオーバーロードを呼ぶ
    *　**this呼び出しはコンストラクタの先頭で！**


```java:Person.java
public class Person {
  public String name;
  public int age;

  //コンストラクタ
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public Person() {
    //コンストラクタの呼び出し
    this("キティちゃん", 46);
  }

  public void show() {
    System.out.printf("%s（%d歳）です。\n", this.name, this.age);
  }
}
```
```java:ConstructorBasic.java
public class ConstructorBasic {

  public static void main(String[] args) {
    var p = new Person();
    p.show(); //キティちゃん（46歳）です。
  }
}
```

##初期化ブロック
* **class{...}直下の名無しブロック**のこと
* **インスタンス化の際にコンストラクタより先に実行**
* **複数のコンストラクタに共通するコードを切りだす**役割
    * まずはコンストラクタを優先して使う
    * 初期化の規定値を表すオーバーロードは初期化ブロックではなくthis呼び出し優先

```java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;

public class Person {
  public String name;
  public int age;
  public LocalDateTime updated;

  //初期化ブロック
  {
    this.updated = LocalDateTime.now();
  }
  //姓名,誕生日から初期化
  public Person(String firstName, String lastName, LocalDate birth) {
    this.name = lastName + " " + firstName;
    this.age = Period.between(birth, LocalDate.now()).getYears();
  }
  //名前,年齢から初期化
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
}
```

##ファクトリーメソッド
* **インスタンス生成を目的としたメソッド**
* インスタンス生成し戻り値で返すのみ
* コンストラクタはprivateにしてファクトリーメソッド経由でのみインスタンス化できるようにする
* `var fc = FactoryClass.getInstance();`
* メリット
    * **自由に命名可能**
        * cf:コンストラクターは不可
    * **インスタンスを生成しなくてもいい**
        * キャッシュしたインスタンスの再利用可能（シングルトンパターンなど）
    * **戻り値の型を抽象型/インターフェース型にできる**
        * メソッドなので戻り値は任意の派生/実装クラスを返せる
        * 実装クラスへの依存をファクトリークラスのみに限定できる

```java
public class FactoryClass {
  //privateコンストラクター
  private FactoryClass() {
    System.out.println("ファクトリー!!");
  }
  //ファクトリーメソッド
  public static FactoryClass getInstance() {
    return new FactoryClass();
  }
}
```