次のコードを想定します。
package Thing;
sub new {
my $this=shift;
bless {@_},$this;
}
sub name {
my $this=shift;
if (@_) {
$this->{_name}=shift;
}
return $this->{_name};
}
次のようにオブジェクトをインスタンス化したとします。
my $o=Thing->new();
$o->name('Harold');
十分です。次のいずれかを使用して、同じものをより迅速にインスタンス化することもできます。
my $o=Thing->new(_name=>'Harold'); # poor form
my $o=Thing->new()->name('Harold');
確かに、属性をコンストラクターに渡して、「フレンドリーな」クラスがより完全にオブジェクトを作成できるようにしました。また、次のコードで clone-type オペレーターを許可することもできます。
my $o=Thing->new(%$otherthing); # will clone attrs if not deeper than 1 level
これはすべて順調です。検証などを可能にするために、メソッドの背後に属性を隠す必要があることを理解しています。
$o->name; # returns 'Harold'
$o->name('Fred'); # sets name to 'Fred' and returns 'Fred'
しかし、これが許可しないのは、それ自体に基づく属性の簡単な操作です。たとえば、次のようになります。
$o->{_name}=~s/old/ry/; # name is now 'Harry', but this "exposes" the attribute
1 つの代替方法は、次のようにすることです。
# Cumbersome, not syntactically sweet
my $n=$o->name;
$n=~s/old/ry/;
$o->name($n);
別の可能性は、次の方法です。
sub Name :lvalue { # note the capital 'N', not the same as name
my $this=shift;
return $this->{_name};
}
これで、次のことができます。
$o->Name=~s/old/ry/;
だから私の質問はこれです...上記の「コーシャ」ですか?それとも、そのように属性を公開するのは悪い形ですか? つまり、それを行うと、「name」メソッドで見つかる可能性のある検証が取り除かれます。たとえば、'name' メソッドが最初の文字を大文字にし、その後に小文字を強制する場合、'Name' (大文字の 'N') はそれをバイパスし、クラスのユーザーにその使用を強制します。
それで、「Name」左辺値メソッドが正確に「コーシャ」でない場合、そのようなことを行うための確立された方法はありますか?
私は、関連付けられたスカラーのようなものを属性として考えました (しかし考えるとめまいがします)。確かに、それは進むべき道かもしれません。
また、おそらく役立つオーバーロードはありますか?
または、次のような代替メソッドを作成する必要があります(機能する場合):
sub replace_name {
my $this=shift;
my $repl=shift;
my $new=shift;
$this->{_name}=~s/$repl/$new/;
}
...
$o->replace_name(qr/old/,'ry');
前もって感謝します...そして注意してください、私はOOP自体にかなり精通していますが、PerlのブランドのOOPについてはあまり経験がありません。
追加情報: 私は自分のインターフェイスで本当にクリエイティブになれると思います... これは私がいじくり回したアイデアですが、実際には限界がないことを示していると思います:
sub name {
my $this=shift;
if (@_) {
my $first=shift;
if (ref($first) eq 'Regexp') {
my $second=shift;
$this->{_name}=~s/$first/$second/;
}
else {
$this->{_name}=$first;
}
}
return $this->{_name};
}
これで、 name 属性を次のいずれかで設定できます
$o->name('Fred');
または私はそれを操作することができます
$o->name(qr/old/,'ry'); # name is now Harry
これはまだ $o->name.=' Jr.'; のようなものを許可していません。しかし、それを追加するのはそれほど難しくありません。一体、calllback 関数を渡せるようにすることはできたのではないでしょうか?