アクセサ(1) アクセサメソッド

オブジェクトがそれぞれ持っている変数の事を「属性」や「プロパティ」などと呼びますが、後からの変更に強くするため、こういった属性に外部からアクセスする時には、「アクセサ」と呼ばれるメソッドを通しますよね。
例えば C++ なら「obj」の「name」属性にアクセスする場合「obj.getName()」(ゲッター)で値を取得して、「obj.setName("Palmo")」(セッター)で値を設定するのが一般的だと思います。(アクセサ=ゲッター+セッター)
また、「get」「set」で分けずに、「name」というメソッドを作って、引数なしで呼ばれた時(obj.name())はゲッター、引数ありで呼ばれた時(name("Palmo"))はセッター、のように1つのメソッドで兼用(オーバーロード)させる事もあります。
Perl の場合は後者の1つのメソッド兼用方式が一般的だそうです。
とりあえず、素直に作ってみます。

package Person;
 
sub new {
    my $class = shift;
    my $self = {
        name => "Somebody",
        age => 0,
    };
    bless $self, $class;
}
 
sub name {
    my $self = shift;
    if (@_) { $self->{name} = shift; }
    return $self->{name};
}
sub age {
    my $self = shift;
    if (@_) { $self->{age} = shift; }
    return $self->{age};
}
sub introduce {
    my $self = shift;
    print "I am " . $self->name();
    print ", " . $self->age() . " years old.\n";
}
 
package main;
$man = Person->new();
$man->introduce();
 
$man->name("Taro");
$man->age(10);
$man->introduce();

メソッド name と age がアクセサメソッドにあたります。どちらもほぼ同じ内容ですね。もし引数が指定されていれば値をセットして、新しい値を返します。
配列を if の条件部にそのまま書いた場合(ブーリアンコンテキストで評価した場合)、配列が空ならば偽、何か入っていれば真なので、if (@_) は「引数が指定されていれば」という意味になります。
メソッド introduce は、アクセサメソッドを通じて取得した値を使って自己紹介しています。同じクラス内なので、本当はオブジェクトの値をそのまま表示してもいいのですが、なるべくアクセサメソッドを通じて値を取得・設定するようにした方が、後々なにかと便利です。
実行結果です。

I am Somebody, 0 years old.
I am Taro, 10 years old.

上手くできていますね。
でも、内容はほとんど変わらないのに、全ての属性に対してアクセサメソッドをいちいち作っていたら、めんどうで仕方ありません。コードの見通しも悪くなります。
この辺りはまだ改良の余地がありそうです。