3

オブジェクトのフィールドへのアクセスを管理する 1 つのセッター メソッドと 1 つのゲッター メソッドをどのように作成しますか? 新しいサブルーチンは次のようになります。

sub new {
    my $class = shift;
    my $self = {@_};        
    bless($self,$class); # turns this into an object
}

新しいオブジェクトの作成は次のようになります。

$foo = Package::new("Package", 
    "bar", $currentBar,
    "baz", $currentBaz,
    );
4

2 に答える 2

9

これは良い考えではありません。

Perl は、use strict;次のような問題を処理するためにの使用を開始しました。

 $employee_name = "Bob";

 print "The name of the employee is $employeeName\n";

変数名のタイプミスはよくある問題でした。を使用use strict;すると、変数を宣言する必要があるため、このようなエラーはコンパイル時にキャッチできます。

ただし、ハッシュ キーとハッシュ参照により、この保護が解除されます。したがって:

my $employee[0] = {}

$employee[0]->{NAME} = "Bob";

print "The name of the employee is " . $employee[0]->{name} . "\n";

複雑なデータ構造について話し始めるときにオブジェクトを使用する理由の 1 つは、次のようなエラーを防ぐためです。

 my $employee = Employee->new;
 $employee->name("Bob");
 print "The name of the employee is " . $employee->Name . "\n";

nameメソッド名がであり ではないため、このエラーはキャッチされますName

ユーザーが独自のメソッドを無作為に作成できるようにすると、オブジェクトを使用することで得られる保護が失われます。

 my $employee = Employee->new;
 $employee->name("Bob");    #Automatic Setter/Getter
 print "The name of the employee is " . $employee->Name . "\n";  #Automatic Setter/Getter

自動セッターとゲッターが原因で、エラーをキャッチできません。これは、ユーザー名が間違っている場合でも、ユーザー名のメソッドが有効であるためです。

実際、オブジェクトがどのように構造化されているかを必ずしも認識しないように、オブジェクトをセットアップしました。fooメソッドとで次のクラスを観察しますbar

 sub new {
    my $class = shift;
    my $foo   = shift;
    my $bar   = shift;

    my $self = {};
    bless $self, $class;

    $self->foo($foo);
    $self->bar($bar);
    return $self;

}

sub foo {
    my $self = shift;
    my $foo  = shift;

    my $method_key = "FOO_FOO_FOO_BARRU";

    if (defined $foo) {
        $self->{$method_key} = $foo;
    }
    return $self->{$method_key};
 }

sub bar {
    my $self = shift;
    my $bar  = shift;

    my $method_key = "BAR_BAR_BAR_BANNEL";

    if (defined $bar) {
        $self->{$method_key} = $bar;
    }
    return $self->{$method_key};
}

とのクラス値をコンストラクターに設定できfooますbar。ただし、私のコンストラクターは、これらの値がどのように格納されているかを知りません。オブジェクトを作成し、getter/setter メソッドに渡すだけです。また、私の 2 つのメソッドは、互いの値をどのように格納するかを知りません。そのため、メソッドのハッシュ キーにこのようなクレイジーな名前を付けることができます。これは、メソッド内でのみ使用でき、他の場所では使用できないためです。

代わりに、私のメソッドfoobarはセッターとゲッターの両方です。fooまたはの値を指定するbarと、その値が設定されます。それ以外の場合は、単に現在の値を返します。

しかし、あなたはすでにこれらすべてを知っており、これを実行しなければならないと主張するでしょう。結構...

やりたいことを処理する 1 つの方法は、AUTOLOADサブルーチンを作成することです。AUTOLOAD サブルーチンは、その名前のメソッド サブルーチンが他にない場合に自動的に呼び出されます。に$AUTOLOADは、呼び出されたクラスとメソッドが含まれています。これを使用して、独自の値を設定できます。

これが私のテストプログラムです。と の 2 つの方法を使用barfooますが、好きな方法を使用しても問題なく動作します。

変更点の 1 つは、値のリストの代わりに、コンストラクターでパラメーター ハッシュを使用することです。これが現代的な方法と見なされることを除いて、実際の違いはありません.

また、メソッド名をすべて小文字に正規化していることにも注意してください。そのよう$object->Foo$object->foo、 、$object-FOOはすべて同じ方法です。このようにして、少なくとも大文字と小文字の間違いをなくします。

use strict;
use warnings;
use feature qw(say);
use Data::Dumper;

my $object = Foo->new({ -bar => "BAR_BAR",
        -foo => "FOO_FOO",
    }
);

say "Foo: " . $object->foo;
say "Bar: " . $object->bar;

$object->bar("barfu");
say "Bar: " . $object->bar;

say Dumper $object;


package Foo;

    sub new {
    my $class =      shift;
    my $param_ref  = shift;

    my $self = {};
    bless $self, $class;

    foreach my $key (keys %{$param_ref}) {

        # May or may not be a leading dash or dashes: Remove them
        (my $method = $key) =~ s/^-+//;

        $self->{$method} = $param_ref->{$key};
    }
    return $self;
}


sub AUTOLOAD {
    my $self  = shift;
    my $value = shift;

    our $AUTOLOAD;

    ( my $method = lc $AUTOLOAD ) =~ s/.*:://;

    if ($value) {
        $self->{$method} = $value;
    }
    return $self->{$method};
}
于 2012-06-04T20:48:19.343 に答える
6

このようなもの...

sub get {
    my $self = shift;
    my $field = shift;
    return $self->{$field};
}

sub set {
    my $self = shift;
    my $field = shift;
    $self->{$field} = shift;
}

...書き込みを可能にします

$obj->set(foo => 'my foo value');
print $obj->get('foo');

しかし、今日では、Mooseを使用するのが非常に一般的です。

于 2012-06-04T18:39:57.813 に答える