سؤال
إذا كان لدي فئة عددية بسيطة مرتبطة تزداد في كل مرة تتم قراءتها، فيمكنني القيام بذلك على النحو التالي:
package Counter;
use strict;
use warnings;
sub TIESCALAR {
my $class = shift;
my $value = 0;
bless \$value, $class;
return \$value;
}
sub FETCH {
my $self = shift;
my $value = $$self;
$$self++;
return $value;
}
sub STORE {
my $self = shift;
$$self = shift;
}
1;
ولكن لإنشاء متغير عداد لا بد لي من استخدامه tie
.يمكنني إنشاء عداد واحد وتصديره.ولكن ما أريد فعله حقًا هو جعل الأمر يبدو OO.يبدو أنه يمكنني إنشاء ملف new
طريقة مثل هذا:
sub new {
my $class = shift;
my $counter;
tie $counter, $class;
return $counter;
}
ثم في البرنامج النصي الرئيسي الخاص بي احصل على عدادين عن طريق القيام بما يلي:
my $counter1 = Counter->new();
my $counter2 = Counter->new();
أفترض أن هذا لا يعمل لأن ربطة العنق لا تنجو من النسخة (قرأت ذلك في المستندات في مكان ما)، فهل هناك ببساطة طريقة للقيام بذلك؟
ملحوظة:أعلم أن الأمر يتعلق فقط بالأسلوب، لكنه سيبدو أكثر صحة للعين.
المحلول
لا يتم تنفيذ سحر التعادل عبر المهمة لأنه ينطبق على المتغير نفسه، وليس القيمة التي يحتوي عليها.لديك بعض الخيارات:
إرجاع مرجع:
sub new {tie my $ret, ...; \$ret}
my $counter = Counter->new;
say $$counter;
التعيين إلى الكرة الأرضية:
our ($counter);
*counter = Counter->new; # same new as above
say $counter;
أو يمكنك تمرير المتغير إلى المُنشئ:
sub new {my $class = shift; tie $_[0], $class}
Counter->new(my $counter);
say $counter;
يمكنك أيضًا إنشاء مُنشئ يعمل بكلتا الطريقتين:
sub new {
my $class = shift;
tie $_[0] => $class;
\$_[0]
}
our $glob; *glob = Counter->new;
Counter->new(my $lexical);
وفي المثالين الأخيرين، tie
تم تمريره $_[0]
مباشرة.والسبب في ذلك هو أن العناصر @_
هي أسماء مستعارة لقائمة الوسيطات، لذا فهي تعمل كما لو كنت قد كتبت my $counter
في ال tie
خط.
وأخيرًا، على الرغم من أن المثال الخاص بك واضح جدًا ويتبع أفضل الممارسات، وفقًا لروح TIMTOWTDI، يمكنك كتابة الفصل بأكمله على النحو التالي:
{package Counter;
sub TIESCALAR {bless [0]}
sub FETCH {$_[0][0]++}
sub STORE {$_[0][0] = $_[1]}
sub new {tie $_[1] => $_[0]; \$_[1]}
}
شيء أخير يجب أن نذكره.على الرغم من أن سؤالك يتعلق بالمتغيرات المرتبطة، يمكنك أيضًا استخدام التحميل الزائد لتحقيق ذلك:
{package Counter;
use overload fallback => 1, '""' => sub {$_[0][0]++};
sub new {bless [0]}
}
my $counter = Counter->new; # overloading survives the assignment
say $counter;
لكنك تفقد القدرة على إعادة ضبط العداد عن طريق التعيين.يمكنك إضافة أ sub set {$_[0][0] = $_[1]}
طريقة ل Counter
.