取消对perl对象的祝福是一个可怕的设计吗?

sr4lhrrt  于 2023-08-06  发布在  Perl
关注(0)|答案(4)|浏览(116)

不祝福Perl对象就意味着有一个糟糕的设计吗?
如果是的话,有谁能解释一下?
顺便说一句,这是引发这个问题的讨论,检查对这个问题的评论

ecfdbz9o

ecfdbz9o1#

需要unbless肯定会引起人们的注意。由于您仍然可以使用对象作为原始数据结构,因此几乎不需要它。
那些对接收不受祝福的哈希引用和对象很挑剔的模块往往有一些不那么挑剔的选项,例如JSON中的allow_blessed和convert_blessed。

e0uiprwp

e0uiprwp2#

一个应用程序是作为散列引用实现的对象,您还希望overload%{}解引用操作符[编辑:并且您还希望支持v5.10.1之前的perls--否则您应该只使用no overloading。]

package Foo;
use overload '+' => sub { $_[0]->get + $_[1] },
             ...,
             '%{}' => sub { return { foo => "bar", this => $_[0] } },
             ...;

字符串
现在,对于任何类型为Foo$foo,尝试访问像$foo->{$key}这样的元素将调用重载的%{}方法,访问将失败。
解决方法是在访问对象的成员时临时更改对象的类型,并在完成后将其更改回来。您可以通过取消对对象的祝福来做到这一点,但更常见的做法(也更容易做到)是将其祝福为垃圾值。

sub Foo::bar {   # access 'bar' member of Foo object
  my $self = shift;
  # $self->{bar} will invoke Foo::{'%{}'}, and we don't wan't that

  my $ref = ref $self;
  unbless($self);    #   or  bless $self, 'Not::An::Object::Name'
  # now $self->{bar} is accessible

  my $value = $self->{bar};
  bless $self, $ref;        # restore object type
  return $value;
}


另一个示例在overload中的“双面引用”一节中给出
我在这里使用这个模式,作为另一个例子。

vof42yt1

vof42yt13#

这是一个无聊而愚蠢的问题。您对unbless没有任何目的,而是从一个晦涩的CPAN模块中随机选择了它,询问它为什么反映了糟糕的设计。您还可以询问如何 * 取消声明 * 一个已用my声明的变量。这在XS代码中也是很有可能的,但我希望这显然是相当愚蠢的?
unbless的问题是,您创建了一个数据结构--从标量变量、文件句柄到嵌套的散列或数组--并调用了bless,以便Perl知道如何解析该对象上的方法调用
所以现在你要unbless它。这将使数据保持不变,主要的区别在于,任何方法调用现在都将导致致命错误

Can't call method ... on unblessed reference

字符串
你的unbless是干什么用的?如果您依赖于Perl来给予此致命错误,那么将undef赋值给导致此致命错误的对象也是很容易的

Can't call method ... on an undefined value


但它的优点是可以破坏数据结构,从而释放内存
如果您想要更可靠的东西,那么,因为引用可能会传递到多个代码段,所以unbless将是action at a distance的一个例子,而action at a distance被比我更多的人所怀疑

xghobddn

xghobddn4#

我认为unbless在我想存储对象数据时很有用,但不存储带有类名的对象数据;准确地说,当你的对象数据的性质意味着是生产数据,而不是为对象自引用工作。

package My::Pkg;
use Storable qw/dclone/;
use Data::Structure::Util qw/unbless/;

sub _distribute_private_attr { 
 $_[0]->{_private_attrs} = {...}
}

sub new {
 my $obj = bless { Foo => [qw/bar/] };
 $obj->_distribute_private_attr();
 return $obj;
}

sub load {
 my $cls = shift;
 my $data = retrieve $_[0];
 my $obj = bless $data, $cls;
  $obj->_distribute_private_attr();
 return $obj
}

sub save {
 my $obj = shift;
 my $data = unbless ( dclone $obj );
 delete $data->{_private_attrs};
 store $data, $_[0];
}
1;

package main;
use Some::Other::Mod;

my $obj = My::Pkg -> new;
$obj->{Bar} = "Baz";
$obj->save ("someFile");

my $obj2 = My::Pkg->load("someFile"); # Now we can do this
my $obj3 = Some::Other::Mod->load("someFile"); # or this
my $data = retrieve "someFile"; # or this

字符串
现在,存储的数据结构可以被其他人使用,而不会扰乱其他类的东西,但是没有任何东西扰乱运行时示例。

相关问题