OHTA412

getterとsetterはできる限り設定しない方がカプセル化できる

オブジェクトの値を取得するgetterメソッドと、値をセットするsetterメソッドは必要最小限の設定にとどめることが大切です。設定するべき時と設定する方法を、PHPを例に説明します。

オブジェクトのプロパティは基本的にprivateにする

クラスベースのオブジェクト指向プログラミング言語では、プロパティの可視性(Visibility)を設定することができます。可視性とは、どこからその値を見ることができるかという設定のことで、アクセス修飾子で定義できます。

class Person {
    public $name; // アクセス修飾子が「public」
    private $age; // アクセス修飾子が「private」

    public function __construct($name, $age){
        $this->name = $name;
        $this->age = $age;
    }
}

$taro = new Person('太郎', 25);

echo $taro->name; // 「太郎」と表示される
echo $taro->age; // エラー

Personクラスからオブジェクトを生成して、そのプロパティを表示した例です。

クラスやアクセス修飾子については、こちらの記事を参考にしてください。

nameプロパティのアクセス修飾子は「public」なので、13行目のように$taroからアクセスできます。しかし、ageプロパティは「private」なので、14行目のように$taroからアクセスしようとするとエラーになります。

全てのプロパティにアクセスできた方が便利そうですが、基本的にプロパティのアクセス修飾子は「private」にします。「public」にした場合は、値を自由に書き換えることも可能になってしまいます。場合によっては、意図するオブジェクトの挙動ではなくなる可能性があります。

$taro = new Person('太郎', 25);

echo $taro->name; // 「太郎」と表示される
$taro->name = '次郎'; // nameプロパティを変更する
echo $taro->name; // 「次郎」と表示される

プロパティを書き換えられて、意図するオブジェクトではなくなった例です。$taroという名前のオブジェクトなのに、nameプロパティは「次郎」になっています。

getterメソッドでプロパティにアクセスする

アクセス修飾子を「private」にしたプロパティにアクセスには、getterメソッドを使います。

class Person {
    private $name;
    private $age;

    public function __construct($name, $age){
        $this->name = $name;
        $this->age = $age;
    }

    // ageを取得するgetterメソッド
    public function getAge(){
        return $this->age;
    }
}

$taro = new Person('太郎', 25);

echo $taro->getAge(); // 「25」と表示される

getterメソッドを使って、ageプロパティを取得した例です。11行目のgetAge()を使ってageプロパティにアクセスできるようになりました。

getterメソッド名の命名規則は、getの後にプロパティ名をつけるのが一般的です。

getterメソッドは必要最小限にする

getterメソッドはプロパティ全てに設定するのではなく、本当にその情報にアクセスする必要があるのかを考慮して、必要最小限にとどめることが大切です。

例えば、先ほどのgetAge()は年齢を返していましたが、成人しているかどうかだけを知りたい場合は年齢を返す必要はありません。

class Person {
    
    …略

    // 成人しているか判定するメソッド
    public function isAdult(){
        return $this->age >= 20 ?? false;
    }
}

$taro = new Person('太郎', 25);

var_dump( $taro->isAdult() ); // bool(true)

成人しているかどうかを判定するメソッドの例です。この場合、年齢にはアクセスできないので、より情報のカプセル化が考慮されています。

カプセル化とは?
カプセル化とは、必要な情報のみをアクセス可能にして、そうでない情報を隠蔽する考え方です。そうすることで外部からの干渉を受けにくく、安全性の高いコードになります。

7行目ではNull合体演算子を使って、trueかfalseを判定しています。「ageプロパティが20以上」という条件式がtrueならその値(true)を、そうでなければfalseを返却しています。

Null合体演算子については、こちらの記事を参考にしてください。

setterメソッドでプロパティに値をセットする

値を取得するにはgetterメソッドを使いますが、値をセットするにはsetterメソッドを使います。

class Person {
    private $name;
    private $age;

    public function __construct($name, $age){
        $this->name = $name;
        $this->age = $age;
    }

    // ageを取得するgetterメソッド
    public function getAge(){
        return $this->age;
    }

    // ageをセットするsetterメソッド
    public function setAge($new_age){
        return $this->age = $new_age;
    }
}

$taro = new Person('太郎', 25);

echo $taro->getAge(); // 「25」と表示される
$taro->setAge(15); // setterメソッドでageをセットする
echo $taro->getAge(); // 「15」と表示される

setterメソッドを使って、ageプロパティを変更した例です。16行目のsetAge()を使ってageプロパティをセットできるようになりました。

setterメソッド名の命名規則は、setの後にプロパティ名をつけるのが一般的です。

setterメソッドもgetterメソッドと同じように、必要最小限の設定にとどめるようにします。

値のバリデーションを行う

上記のsetAge()は、引数の値をそのままプロパティにセットしていますが、実際にはバリデーションを行う必要があります。このままでは、ageプロパティに文字列なども設定できてしまいます。今回の例では「0から100までの整数値であれば値をセットする」というようなバリデーションが必要になってきます。

どのような値がセットされるべきなのか、状況に応じてバリデーションを設定します。