كيف يمكنني إلغاء تحديد كائن في بيرل؟
سؤال
من عند يبارك بيرلوك:
bless REF,CLASSNAME
هذه الوظيفة تخبر Thingy المشار إليها
REF
هو الآن
كائن فيCLASSNAME
صفقة.
هل هناك أي طريقة للحصول على بنية غير مجمعة دون نسخ غير ضروري؟
المحلول
unbless($ref)
قم بإزالة البركة من أي كائنات موجودة داخل بنية البيانات التي تم تمريرها.
#!/usr/bin/perl
use strict; use warnings;
use Scalar::Util qw( refaddr );
use Data::Structure::Util qw( unbless );
my $x = bless { a => 1, b => 2 } => 'My';
printf "%s : %s\n", ref $x, refaddr $x;
unbless $x;
printf "%s : %s\n", ref $x, refaddr $x;
انتاج:
My : 237356 HASH : 237356
نصائح أخرى
البيانات :: الهيكل :: util لديه unbless
الوظيفة التي ستفعل ذلك من أجلك. كما يشير إريك ، JSON :: XS لن تقبل عادة المراجع المباركة (على الرغم من أنني أتمنى أن تتجاهل ذلك فقط والتعامل مع بنية البيانات). لا توجد طريقة للتغلب عليها في هذه الحالة.
ولكن فكر في سبب اعتقادك أنك بحاجة إلى إلغاء التعبير عنها. هل تفعل هذا لأحد الفصول الدراسية الخاصة بك أو فئة مختلفة؟ هذا يبدو بشكل مثير للريبة مثل الشيء الخطأ الذي يجب فعله. قد يكون هناك طريقة أفضل.
لديك نفس المشكلة مثل كسر التغليف لأنك يجب أن تفترض أنك تعرف البنية الداخلية للمرجع. إذا كنت ستفعل ذلك ، فيمكنك فقط تجاهل الأشياء الموجهة للكائنات والوصول إلى الهيكل مباشرة.
إذا كنت ستفعل ذلك لفصلك الخاص ، ففكر في توفير طريقة لإرجاع بنية البيانات (والتي لا يجب أن تكون الهيكل الأصلي) بدلاً من تغيير الكائن.
ذكرت في تعليق متابعة أنك قد تقوم بذلك للالتفاف على بعض سلوك مجموعة أدوات القالب. كان لدي هذا الموقف بطريقتين اعتمادًا على الموقف:
- تمرير البيانات التي تحتاجها فقط إلى القالب بدلاً من الكائن بأكمله.
- أضف طرقًا إلى الكائن للحصول على البيانات التي تريدها في القالب.
Perl هو DWIM ، ولكن TT هو حتى dwimmier ، وهو أمر مؤسف في بعض الأحيان.
إليك اختراق سريع حيث حدد TO_JSON
في UNIVERSAL
لذلك ينطبق على جميع الكائنات. إنه يجعل نسخة عميقة ، وتبدلها ، ويعيد بنية البيانات.
#!perl
use v5.10;
sub UNIVERSAL::TO_JSON {
my( $self ) = shift;
use Storable qw(dclone);
use Data::Structure::Util qw(unbless);
my $clone = unbless( dclone( $self ) );
$clone;
}
my $data = bless {
foo => bless( [], 'Local::Array' ),
quack => bless( {
map { $_ => bless [$_, $_**2], 'Local::Array' }
grep { is_prime } 1 .. 10
}, 'Local::Hash' ),
}, 'Local::Hash';
use JSON::XS;
my $jsonner = JSON::XS->new->pretty->convert_blessed(1);
say $jsonner->encode( $data );
إذا كنت تعرف ما الذي يتم دعم كائنك ، فيمكنك القيام بذلك دون استخدام الحزم.
التجزئة
$obj = bless {}, 'Obj';
print ref $obj, "\n";
$obj = { %$obj };
print ref $obj, "\n";
مجموعة مصفوفة
$obj = bless [], 'Obj';
print ref $obj , "\n";
$obj = [ @$obj ];
print ref $obj, "\n";
العددية
$obj = bless \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";
Acme :: لعنة :)
تحديث: شكرا لك إيفان! أنا خلط الوحدات النمطية. في الواقع أردت أن أعطي رابطًا acme :: اللعنة :))
ملاحظة أنظر أيضا Acme :: العطس :)
PPS ليس له أي فائدة حقيقية ، ولهذا السبب هو Acme::
. انظر بوست براين.