最近の記事
- 9/1 - 将棋始めました
- 5/16 - サーバー引っ越し
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
Entering Passive Mode
スカラに tie されたオブジェクトを隠蔽することで、
プロパティの代入・取得ハンドラを書くことができた。
今日は、値の検証コードをいれてみよう。
昨日作った STORE ルーチンを修正すれば、
値を検証をすることは簡単にできる。
sub STORE {
my ($this, $value) = @_;
if ($value < 140000) { die "I can't agree you offered!" }
$$this = $value;
}
スカラ変数は、値を一つ格納するだけしかできないので、
スカラ用の tie オブジェクトは非常にシンプルである。
これらが実装する必要があるのは、以下のメソッドだけだ。
TIESCALAR, STORE, FETCH
TIESCALAR は tie から呼ばれるクラスのコンストラクタで、
STORE は、スカラに値を代入する際に、
FETCH は、スカラから値を取得する際に呼び出される。
では、Employee クラスを拡張してみよう。
lvalue を使えば、プロパティ構文が使えるが、
代入はサブルーチンの中では行われない。
となると、どうやって値を検証するか。
さて substr を思い出してみよう。
substr には代入ができたはずだ。
substr も lvalue 属性がついている。
どうなっているか調べてみよう。
調べるために、注意しないといけないこともある。
lvalue サブルーチンは特別な効果を持つため、
構文上戻り値を直接代入しているように見えても
実際の、lvalue サブルーチンの挙動は異なる。
プロパティには、他にも重要な機能がある。
それは、setter/getter による値の検証や、
読み取り専用、書き込み専用などの制限だ。
フィールドとして公開した場合、ただの変数となるので、
外部から自由にアクセスできてしまうが、
プロパティとした場合は、setter/getter が、
代入値の検証や、取得の可否などのチェック機能となる。
昨日の時点で、構文としてのプロパティは実装できたが、
それ以外の部分はどうだろうか。
lvalue が任意のサブルーチンに使えるということは、
クラスインスタンスのメソッドとしても使えるということだ。
理由は、Perl におけるメソッドが、
単に、クラスの名前と同じパッケージに定義された、
サブルーチンであるからである。
サブルーチンをメソッドとして使う場合、
暗黙に一つ目の引数としてインスタンスが渡される。
それだけの差なのだ。
lvalue 属性は、組み込み関数だけでなく、
自作サブルーチンでも使うことができる。
サブルーチンの属性による拡張は、
Perl 5.6 で実装されており、特殊な構文によって指定する。
sub 関数名 : 属性名 {
# 文……
}
: の後に、属性の名前を指定することで、
サブルーチンが特別な意味を持つようになる。
では、左辺値になるサブルーチンとはなんだろうか。
Perl には、substr という関数(サブルーチン)がある。
文字列の操作をするにはおなじみの関数だ。
しかしこの substr 関数、ただものではないのだ。
my $value = 'abcdefgh';
substr($value, 3, 4) = '-CRACKED!-';
print $value;
実行すると、以下のような出力が得られる。
Perl によるアクセサの実装は以下のようだった。
$value = $jack->salary;
$jack->salary($new_value);
Perl では、利便性や実装の手間の関係で、
setter/getter に同じメソッドを流用する。
高級言語では、通常このような実装は嫌われる。
同じ名前のメソッドが異なる挙動をするというのは、
設計者視点で考えても、使用者視点で考えても、
あまり好ましいことではないのだ。
Perl のオブジェクトは、ただのリファレンスであり、
上級言語風に言うと、連想配列から継承したクラスなのだ。
(例外もあるが、大抵は連想配列を使っている)
そのため、インスタンスに対して、
ハッシュのリファレンスとしてアクセスできてしまうのだ。
Perl には、アクセス制限なんてものは一切ない。
その代わりにあるのは……紳士協定だ。(笑)
連想配列への直接アクセスは止めましょって協定ですな。
さて、これからプロパティについて考えていくので、
その題材となるクラスを考えよう。
今回は、Employee オブジェクトを作る。
Employee = 従業員だ。プログラミングのサンプルとして、
どこにでも出てきそうな名前だ。
Employee というオブジェクトは、以下の属性を持つ。
・名前
・性別
・体重
・給料