2006 年 4 月 4 日 23 時 48 分

Perl のアクセサ


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


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

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

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

では、アクセサを定義してみよう。

========== Employee.pm ==========

package Employee;

use v5.6.1;
use strict;
use warnings;

BEGIN {
    our $Version = '0.02';
}

sub new {
    my ($package, %identity) = @_;
    $package = (ref $package or $package or __PACKAGE__);
    bless(\%identity, $package);
}

sub name {
    return $_[0]->{'name'};
}

sub gender {
    return $_[0]->{'gender'};
}

sub weight {
    return $_[0]->{'weight'};
}

sub salary {
    @_ == 2 ? $_[0]->{'salary'} = $_[1] : $_[0]->{'salary'};
}

1;

========== end of Employee.pm ==========


========== EmployeeTest.pl ==========

#!/usr/local/bin/perl

use strict;
use warnings;
use lib '.';
use Employee;

my $jack = Employee->new(
    'name'  => 'Jack',
    'gender' => 'male',
    'salary' => 160000,
    'weight' => '65kg',
);

$\ = "\n";

print "Package: ", ref($jack);
print "Name: ", $jack->name;
print "Gender: ", $jack->gender;
print "Weight: ", $jack->weight;
print "Salary: ", $jack->salary;

$jack->salary(200000);

print "Salary: ", $jack->salary;

========== end of EmployeeTest.pl ==========

実行してみる。

$ ./EmployeeTest.pl
Package: Employee
Name: Jack
Gender: male
Weight: 65kg
Salary: 160000
Salary: 200000

基本的には代わらないが、
アクセサ経由での呼び出しだ。

getter は、引数が必要ないため、括弧を省略できる。
このため、これが非常にプロパティっぽく見えるのだ。

ただ、setter に関しては問題点もある。

Perl は素早くコードを書くため、
色々と省略することができる言語である。
その性質があるためか、アクセサに関しても、昔から、
setter/getter に同じメソッドを使う実装が多い。

salary はその例だ。

print $jack->salary;
$jack->salary(200000);

どうだろうか。違和感がないだろうか。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.