(イ)ミュータブルとは?
作成した時の状態から更新できるかの違いです。
特別な理由がない限り、イミュータブルなクラスとすることを勧めます。
ミュータブル | イミュータブル | |
---|---|---|
更新 | ○ | × |
値の入れ方 | setter | constructor |
ミュータブルなクラス
/*
* 単純な構造体となってしまいがち
* (データの出し入れだけで振る舞いがない)
*/
public class User {
private String firstName;
private String familyName;
/** constructor */
public User() {}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return this.firstName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public String getFamilyName() {
return this.familyName;
}
}
public class 山田太郎 {
private User user;
/** constructor */
public 山田太郎() {
User user = new User();
/*
* Bad: コード上では入れ忘れを検知できない
*/
// user.setFirstName("太郎");
user.setFamilyName("山田");
this.user = user;
}
public String getFullName() {
/*
* Bad: 不要な更新ができてしまう
*/
this.user.setFirstName("鈴木");
/*
* 利用側で処理を書きがち
* →色んな所に同じ処理が散らばる
*/
return this.user.getFirstName() + this.user.getFamilyName();
}
}
イミュータブルなクラス
/*
* 単純な構造体ではないので、必要なモノの取捨選択ができる
*/
public class User {
private String firstName;
private String familyName;
/** constructor */
public User(String firstName, String familyName) throws Exception {
/*
* Good: 生成時に整合性の判断ができる
* →ここで判断できない場合は利用側に任せることとなる
*/
if (Objects.isNull(firstName) || Objects.isNull(familyName)) {
throw new Exception();
}
this.firstName = firstName;
this.familyName = familyName;
}
public String getFullName() {
return this.familyName + this.firstName;
}
}
public class 山田太郎 {
private User user;
/** constructor */
public 山田太郎() throws Exception {
/*
* Good: コードで入れ忘れを検知できない
* Bad?: 引数が膨大となる可能性がある
* →設計を見直すきっかけとなる
*/
this.user = new User("太郎", "山田");
}
public String getFullName() {
return this.user.getFullName();
}
}