perl - بيرل موس أسيسورس ولدت على الطاير



attributes moose (1)

انظر الجزء التالي من رمز بيرل الذي يقوم على موس:

$BusinessClass->meta->add_attribute($Key => { is        => $rorw,
                                              isa       => $MooseType,
                                              lazy      => 0,
                                              required  => 0,
                                              reader    => sub { $_[0]->ORM->{$Key} },
                                              writer    => sub { $_[0]->ORM->newVal($Key, $_[1]) },
                                              predicate => "has_$Key",
                                            });

أتلقى الخطأ:

bad accessor/reader/writer/predicate/clearer format, must be a HASH ref at /usr/local/lib/perl5/site_perl/mach/5.20/Class/MOP/Class.pm line 899

سبب الخطأ واضح: يجب أن يكون القارئ والكاتب أسماء سلسلة من الوظائف.

ولكن ماذا تفعل في هذه الحالة بالتحديد؟ أنا لا أريد إنشاء وظيفة جديدة لكل من حقول أورم مائة (السمة أورم هنا هو تجزئة مرتبطة). لذلك لا أستطيع تمرير سلسلة هنا، ولست بحاجة إلى إغلاق.

وبالتالي، فإن احتياجات الترميز الخاصة بي أدت إلى تناقض. أنا لا أعرف ما يجب القيام به.

ما سبق هو جزء من رمز حقيقي. الآن أقدم مثالا بسيطا:

#!/usr/bin/perl

my @Fields = qw( af sdaf gdsg ewwq fsf ); # pretend that we have 100 fields

# Imagine that this is a tied hash with 100 fields 
my %Data = map { $_ => rand } @Fields;

package Test;
use Moose;

foreach my $Key (@Fields) {
  __PACKAGE__->meta->add_attribute($Key => { is        => 'rw',
                                             isa       => 'Str',
                                             lazy      => 0,
                                             required  => 0,
                                             reader    => sub { $Data{$Key} },
                                             writer    => sub { $Data{$Key} = $_[1] },
                                           });
}

يؤدي تشغيله إلى:

$ ./test.pl 
bad accessor/reader/writer/predicate/clearer format, must be a HASH ref at /usr/lib/i386-linux-gnu/perl5/5.22/Class/MOP/Class.pm line 899
    Class::MOP::Class::try {...}  at /usr/share/perl5/Try/Tiny.pm line 92
    eval {...} at /usr/share/perl5/Try/Tiny.pm line 83
    Try::Tiny::try('CODE(0x9dc6cec)', 'Try::Tiny::Catch=REF(0x9ea0c60)') called at /usr/lib/i386-linux-gnu/perl5/5.22/Class/MOP/Class.pm line 904
    Class::MOP::Class::_post_add_attribute('Moose::Meta::Class=HASH(0x9dc13f4)', 'Moose::Meta::Attribute=HASH(0x9dc6b5c)') called at /usr/lib/i386-linux-gnu/perl5/5.22/Class/MOP/Mixin/HasAttributes.pm line 39
    Class::MOP::Mixin::HasAttributes::add_attribute('Moose::Meta::Class=HASH(0x9dc13f4)', 'Moose::Meta::Attribute=HASH(0x9dc6b5c)') called at /usr/lib/i386-linux-gnu/perl5/5.22/Moose/Meta/Class.pm line 572
    Moose::Meta::Class::add_attribute('Moose::Meta::Class=HASH(0x9dc13f4)', 'af', 'HASH(0x9ea13a4)') called at test.pl line 18

أنا لا أعرف ماذا أفعل (كيفية إنشاء "ديناميكية" (يشبه الإغلاق) أسيسورس، دون كتابة وظيفة فردية لكل من 100 حقول؟)


أعتقد أن تغيير القارئ والكاتب أساليب مثل هذا يتطلب مستوى غير صحي من الجنون. إذا كنت ترغب في ذلك، نلقي نظرة على التعليمات البرمجية المصدر من الفئة :: موب :: الطريقة :: أسيسور ، والذي يستخدم تحت غطاء محرك السيارة لإنشاء المساعدون.

بدلا من ذلك، أقترح فقط الكتابة (أو إرفاق) وظيفة القراء موس التي تم إنشاؤها باستخدام طريقة تعديل around . للحصول على ذلك للعمل مع الطبقات الفرعية، يمكنك استخدام الفئة :: الطريقة :: المحولات بدلا من موس around .

package Foo::Subclass;
use Moose;
extends 'Foo';

package Foo;
use Moose;

package main;
require Class::Method::Modifiers; # no import because it would overwrite Moose

my @Fields = qw( af sdaf gdsg ewwq fsf );    # pretend that we have 100 fields

# Imagine that this is a tied hash with 100 fields
my %Data = map { $_ => rand } @Fields;

my $class = 'Foo::Subclass';
foreach my $Key (@Fields) {
    $class->meta->add_attribute(
        $Key => {
            is       => 'rw',
            isa      => 'Str',
            lazy     => 0,
            required => 0,
        }
    );

    Class::Method::Modifiers::around( "${class}::$Key", sub {
        my $orig = shift;
        my $self = shift;

        $self->$orig(@_);    # just so Moose is up to speed

        # writer
        $Data{$Key} = $_[0] if @_;

        return $Data{$Key};
    });
}

ثم قم بتشغيل اختبار.

package main;
use Data::Printer;
use v5.10;

my $foo = Test->new;
say $foo->sdaf;
$foo->sdaf('foobar');
say $foo->sdaf;

p %Data;
p $foo;

وهنا ستدوت / ستدير من الجهاز الخاص بي.

{
    af     0.972962507120432,
    ewwq   0.959195914302605,
    fsf    0.719139421719849,
    gdsg   0.140205658312095,
    sdaf   "foobar"
}
Foo::Subclass  {
   Parents       Foo
    Linear @ISA   Foo::Subclass, Foo, Moose::Object
    public methods (6) : af, ewwq, fsf, gdsg, meta, sdaf
    private methods (0)
    internals: {
        sdaf   "foobar"
    }
}
0.885114977459551
foobar

كما ترون، موس لا يعرف حقا عن القيم داخل التجزئة، ولكن إذا كنت تستخدم أسيسورس، فإنه سيتم قراءتها وكتابتها. الكائن موس سوف تملأ ببطء مع قيم جديدة عند استخدام الكاتب، ولكن على خلاف ذلك القيم داخل الكائن موس لا يهم حقا.