首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Moo(se),之前和继承

Moo(se),之前和继承
EN

Stack Overflow用户
提问于 2014-02-03 09:44:22
回答 1查看 1K关注 0票数 2

我有一个Moo(se)类,它有许多方法,它们的顶部都有完全相同类型的“卫士声明”。与几次编写相同的代码不同,我认为我可以将语句放入一个“前面”的方法修饰符中,这是非常完美的。除非这个类是子类,因为这样就永远不会调用“先保护”。

代码语言:javascript
复制
package Foo;
use feature 'say';
use Moose;

has '_init' => (
  is      => 'rw',
  isa     => 'Bool',
  default => 0
);

sub init {
  shift->_init(1);
}

sub method {
  say "in Foo::method";
}

before method => sub {
  my $self = shift;
  warn "==> Foo is not initialized\n" unless $self->_init;
};


package Bar;
use feature 'say';
use Moose;
extends 'Foo';

sub method {
  say "in Bar::method";
}


package main;
use feature 'say';

my $foo = Foo->new;
say "foo the wrong way:";
$foo->method;

say "foo the right way:";
$foo->init;
$foo->method;

my $bar = Bar->new;
say "bar the wrong way:";
$bar->method;

然后输出(添加了一些新行):

代码语言:javascript
复制
foo the wrong way:
==> Foo is not initialized
in Foo::method

foo the right way:
in Foo::method

bar the wrong way:
in Bar::method

我假设这种行为是故意的,但是是否有任何(很好的)方法来确保所有子类也继承“any”方法修饰符/守护语句?或者有不同的方法来完成这个任务(我怀疑这是一个相当常见的构造)。注意,一个异常将抛出在真正的卫士语句中,但是在示例代码中,“警告”要简单得多。

我更喜欢使用Moo,因为我不使用任何需要拖把的特性,但是Moo和Moose在这个问题上的工作方式完全一样。

编辑使用角色的

如果为此添加一个Role (按照tobyink的建议),并添加另一种方法来使事情更“真实”一些,我就得到了一个特殊的结果。

代码语言:javascript
复制
package Warning::NotInit;
use feature 'say';
use Moose::Role;

has '_init' => (is => 'rw', isa => 'Bool', default => 0);

before qw/ m1 m2 / => sub {
  my $self  = shift;
  my $class = ref($self);
  warn "==> $class is not initialized\n" unless $self->_init;
};

package Foo;
use feature 'say';
use Moose;
with 'Warning::NotInit';

sub init { shift->_init(1) }
sub m1   { say "in Foo::m1" }
sub m2   { say "in Foo::m2" }

package Bar;
use feature 'say';
use Moose;
extends 'Foo';
with 'Warning::NotInit';

sub m1 { say "in Bar::m1" }


package main;
use feature 'say';

在子类中调用未重写的方法时,before方法将被调用两次。

代码语言:javascript
复制
my $bar = Bar->new;
say "bar the wrong way:";
$bar->m1;
$bar->m2;

输出:

代码语言:javascript
复制
bar the wrong way:
==> Bar is not initialized
in Bar::m1

==> Bar is not initialized
==> Bar is not initialized
in Foo::m2

为什么叫两次?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-03 10:07:10

是的,方法修饰符不是这样工作的。before修饰符成为方法本身的一部分。当您重写子类中的方法时,您将覆盖超类行为的全部--也就是说,您也要重写方法修饰符。

您可以通过将方法修饰符分解成可以应用于每个类的角色来解决这个问题,如下所示:

代码语言:javascript
复制
package Warning::NotInit;
use feature 'say';
use Moose::Role;

has '_init' => (
  is      => 'rw',
  isa     => 'Bool',
  default => 0
);

before method => sub {
  my $self  = shift;
  my $class = ref($self);
  warn "==> $class is not initialized\n" unless $self->_init;
};

package Foo;
use feature 'say';
use Moose;
with 'Warning::NotInit';

sub init {
  shift->_init(1);
}

sub method {
  say "in Foo::method";
}

package Bar;
use feature 'say';
use Moose;
extends 'Foo';
with 'Warning::NotInit';

sub method {
  say "in Bar::method";
}


package main;
use feature 'say';

my $foo = Foo->new;
say "foo the wrong way:";
$foo->method;

say "foo the right way:";
$foo->init;
$foo->method;

my $bar = Bar->new;
say "bar the wrong way:";
$bar->method;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21523948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档