修改继承的访问器并保留修饰符

发布于 2024-11-24 06:53:30 字数 1065 浏览 4 评论 0原文

我正在尝试使用更具体的子类继承和扩展基类,该子类从访问器中删除所需的属性并指定延迟构建的默认值。但是,这样做时,派生类不再将 around 子例程包装在对访问器的调用周围。

我的定义做错了什么?

编辑:我应该声明我可以简单地继承访问器而不修改它,并且 around 修饰符仍然有效,并且我知道我可以执行一些操作,例如将访问器设置为具有 getter,然后使用名称定义一个 getter 方法访问器(即 sub attr { my $self = shift; my $value = $self->_get_attr; return "The value of attr is '$value'"; })。我只是很惊讶 around 修饰符如此容易被丢弃。

use strict;
use warnings;
use 5.010;

package My::Base;
use Moose;

has 'attr' => (is => 'ro', isa => 'Str', required => 1);

around 'attr' => sub {
  my $orig = shift;
  my $self = shift;

  my $response = $self->$orig(@_);
  return "The value of attr is '$response'"
};

package My::Derived;
use Moose;

extends 'My::Base';

has '+attr' => (required => 0, lazy_build => 1);

sub _build_attr {
  return "default value";

}

package main;

my $base = My::Base->new(attr => 'constructor value');
say $base->attr; # "The value of attr is 'constructor value'"

my $derived = My::Derived->new();
say $derived->attr; # "default value"

I'm trying to inherit and extend a base class with a more specific child class that removes the required attribute from an accessor and specifies a lazily built default. However, when doing so, the derived class no longer wraps the around subroutine around calls to the accessor.

What am I doing wrong in my definition?

Edit: I should state that I can simply inherit the accessor without modifying it and the around modifier still works, and I'm aware I can do something like set the accessor to have a getter, then define a getter method with the name of the accessor (i.e. sub attr { my $self = shift; my $value = $self->_get_attr; return "The value of attr is '$value'"; }). I'm simply surprised the around modifier gets dumped so easily.

use strict;
use warnings;
use 5.010;

package My::Base;
use Moose;

has 'attr' => (is => 'ro', isa => 'Str', required => 1);

around 'attr' => sub {
  my $orig = shift;
  my $self = shift;

  my $response = $self->$orig(@_);
  return "The value of attr is '$response'"
};

package My::Derived;
use Moose;

extends 'My::Base';

has '+attr' => (required => 0, lazy_build => 1);

sub _build_attr {
  return "default value";

}

package main;

my $base = My::Base->new(attr => 'constructor value');
say $base->attr; # "The value of attr is 'constructor value'"

my $derived = My::Derived->new();
say $derived->attr; # "default value"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

起风了 2024-12-01 06:53:30

根据 stvn 对 关于 perlmonks 的相同问题的回复,问题是:

实际上,它并没有删除“around”修饰符,您只是
在派生类中创建一个新的访问器,该访问器本身不是
周围编辑。请允许我解释一下...

当您创建属性时,Moose 会编译访问器方法
您并将它们安装在定义它们的包中。这些
访问器方法没有什么神奇的(事实上,Moose 中没有什么神奇的)
非常神奇,复杂,是的,但很神奇,不是),所以它们是继承的
就像任何其他方法一样通过子类进行。

当你“围绕”一个方法时(就像你在这里所做的那样),Moose 会提取
从包装中取出子部件,将其包裹起来,然后用
包装版。这一切都只发生在本地包中,
方法修饰符不知道(或关心)有关继承的任何信息。

当您使用 +attr 形式更改属性定义时,Moose
在超类列表中查找属性元对象,然后
克隆该属性元对象,应用您请求的更改
然后将该属性安装到本地类中。结果是
所有访问器方法都重新编译到本地类中,
因此覆盖超类中定义的内容。

它不会反过来,即访问器是从 ISA 中最底层的类构建的,然后依次应用 ISA 堆栈上的周围修饰符。

Per a response from stvn for the same question on perlmonks, the issue is:

Actually, it is not removing the 'around' modifier, you are simply
creating a new accessor in your derived class, which itself is not
around-ed. Allow me to explain ...

When you create an attribute, Moose compiles the accessor methods for
you and installs them in the package in which they are defined. These
accessor methods are nothing magical (in fact, nothing in Moose is
very magical, complex yes, but magical no), and so they are inherited
by subclasses just as any other method would be.

When you "around" a method (as you are doing here) Moose will extract
the sub from the package, wrap it and replace the original with the
wrapped version. This all happens in the local package only, the
method modifiers do not know (or care) anything about inheritance.

When you change an attributes definition using the +attr form, Moose
looks up the attribute meta-object in the superclass list and then
clones that attribute meta-object, applying the changes you requested
and then installs that attributes into the local class. The result is
that all accessor methods are re-compiled into the local class,
therefore overriding the ones defined in the superclass.

It doesn't go the other way around, where the accessor is built from the bottommost class in the ISA, then the around modifiers up the ISA stack are applied in turn.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文