Entering Passive Mode

カテゴリ 'Perl' の記事
< 1 2 3 4 5 6 7... >

値の検証と汎用化

スカラに tie されたオブジェクトを隠蔽することで、
プロパティの代入・取得ハンドラを書くことができた。
今日は、値の検証コードをいれてみよう。

昨日作った STORE ルーチンを修正すれば、
値を検証をすることは簡単にできる。

sub STORE {
    my ($this, $value) = @_;
    if ($value < 140000) { die "I can't agree you offered!" }
    $$this = $value;
}

スカラの tie

スカラ変数は、値を一つ格納するだけしかできないので、
スカラ用の tie オブジェクトは非常にシンプルである。
これらが実装する必要があるのは、以下のメソッドだけだ。

TIESCALAR, STORE, FETCH

TIESCALAR は tie から呼ばれるクラスのコンストラクタで、
STORE は、スカラに値を代入する際に、
FETCH は、スカラから値を取得する際に呼び出される。

では、Employee クラスを拡張してみよう。

代入値の検証はどうするか

lvalue を使えば、プロパティ構文が使えるが、
代入はサブルーチンの中では行われない。
となると、どうやって値を検証するか。

さて substr を思い出してみよう。
substr には代入ができたはずだ。
substr も lvalue 属性がついている。
どうなっているか調べてみよう。

調べるために、注意しないといけないこともある。
lvalue サブルーチンは特別な効果を持つため、
構文上戻り値を直接代入しているように見えても
実際の、lvalue サブルーチンの挙動は異なる。

lvalue の限界

プロパティには、他にも重要な機能がある。
それは、setter/getter による値の検証や、
読み取り専用、書き込み専用などの制限だ。

フィールドとして公開した場合、ただの変数となるので、
外部から自由にアクセスできてしまうが、
プロパティとした場合は、setter/getter が、
代入値の検証や、取得の可否などのチェック機能となる。

昨日の時点で、構文としてのプロパティは実装できたが、
それ以外の部分はどうだろうか。

代入可能なメソッド

lvalue が任意のサブルーチンに使えるということは、
クラスインスタンスのメソッドとしても使えるということだ。

理由は、Perl におけるメソッドが、
単に、クラスの名前と同じパッケージに定義された、
サブルーチンであるからである。

サブルーチンをメソッドとして使う場合、
暗黙に一つ目の引数としてインスタンスが渡される。
それだけの差なのだ。

lvalue 属性

lvalue 属性は、組み込み関数だけでなく、
自作サブルーチンでも使うことができる。

サブルーチンの属性による拡張は、
Perl 5.6 で実装されており、特殊な構文によって指定する。

sub 関数名 : 属性名 {
    # 文……
}

: の後に、属性の名前を指定することで、
サブルーチンが特別な意味を持つようになる。

左辺値になるサブルーチン

では、左辺値になるサブルーチンとはなんだろうか。

Perl には、substr という関数(サブルーチン)がある。
文字列の操作をするにはおなじみの関数だ。
しかしこの substr 関数、ただものではないのだ。

my $value = 'abcdefgh';
substr($value, 3, 4) = '-CRACKED!-';
print $value;

実行すると、以下のような出力が得られる。

setter/getter の設計思想

Perl によるアクセサの実装は以下のようだった。

$value = $jack->salary;
$jack->salary($new_value);

Perl では、利便性や実装の手間の関係で、
setter/getter に同じメソッドを流用する。

高級言語では、通常このような実装は嫌われる。
同じ名前のメソッドが異なる挙動をするというのは、
設計者視点で考えても、使用者視点で考えても、
あまり好ましいことではないのだ。

Perl のアクセサ

Perl のオブジェクトは、ただのリファレンスであり、
上級言語風に言うと、連想配列から継承したクラスなのだ。
(例外もあるが、大抵は連想配列を使っている)

そのため、インスタンスに対して、
ハッシュのリファレンスとしてアクセスできてしまうのだ。

Perl には、アクセス制限なんてものは一切ない。
その代わりにあるのは……紳士協定だ。(笑)
連想配列への直接アクセスは止めましょって協定ですな。

題材

さて、これからプロパティについて考えていくので、
その題材となるクラスを考えよう。

今回は、Employee オブジェクトを作る。
Employee = 従業員だ。プログラミングのサンプルとして、
どこにでも出てきそうな名前だ。

Employee というオブジェクトは、以下の属性を持つ。

・名前
・性別
・体重
・給料

< 1 2 3 4 5 6 7... >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS