为什么子类不继承其父类的常量?

时间:2011-10-19 16:53:08

标签: perl oop inheritance constants moose

所以我正在谈论我的Moosey业务,我认为在我使用数字的地方使用常数可能会很好,以明确这些数字的含义或以后更改

所以在父类中我添加了标准的'use constant'

package Parent;
    use constant {
        NO_LEVEL => 0,
        MY_LEVEL => 1,
        YOUR_LEVEL => 2,
    };

package Child;
extends 'Parent';

#just to demonstrate that child can or cannot access the constant
sub printMyLevel{
 print MY_LEVEL;
}

但是子类不知道父级中设置的常量!卫生署!

我猜我必须做一些Moose魔法才能让它正常工作,或完全不同。我在这个问题上的搜索没有得出任何结果= /

5 个答案:

答案 0 :(得分:11)

常量是子程序。

{
    package Parent;
    use Moose;
    use namespace::autoclean;

    use constant {
        NO_LEVEL => 0,
        MY_LEVEL => 1,
        YOUR_LEVEL => 2,
    };
    __PACKAGE__->meta->make_immutable;
};

{
    package Child;
    use Moose;
    use namespace::autoclean;

    extends 'Parent';

    sub printMyLevel {
        my $self = shift;
        my $class = ref $self;

        print $class->MY_LEVEL;
    }
    __PACKAGE__->meta->make_immutable;
}

package main;

my $child = Child->new;
$child->printMyLevel;

请记住,常量是具有空原型的子程序。 perl利用此功能在编译期间内联它们。但是,方法调用忽略了原型,因此不会内联以这种方式访问​​的可继承常量。

答案 1 :(得分:6)

这实际上是在documentation中提到的,如果只是传递:

  

“常量属于它们所定义的包。要引用另一个包中定义的常量,请指定完整的包名称,如Some::Package::CONSTANT中所示。常量可以由模块导出,也可以调用作为类或实例方法,即Some::Package->CONSTANT$obj->CONSTANT,其中$objSome::Package的实例。子类可以定义自己的常量来覆盖它们中的那些基类。“

答案 2 :(得分:4)

将它们称为方法。

sub printMyLevel{
    my ( $self, ) = $_;
    print $self->MY_LEVEL;
}

答案 3 :(得分:4)

由于常量是子例程,并且你可以通过调用它们来获得继承,因为 bit已经被覆盖到了死亡,这里有一些不同的东西。

如果您知道自己只使用单个文件,则可以使用词法常量来桥接包:

package Parent;
    our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL);
    *NO_LEVEL   = \0;  # this split declaration installs aliases to numbers
    *MY_LEVEL   = \1;  # into the lexicals.  since numbers are constants
    *YOUR_LEVEL = \2;  # to perl, the aliased names are also constants

package Child;

# just to demonstrate that anything below can access the constants
sub printAll {
    print "$NO_LEVEL $MY_LEVEL $YOUR_LEVEL\n";
}

Child->printAll; # 0 1 2

eval {$NO_LEVEL = 3} or print "error: $@\n";
# error: Modification of a read-only value attempted at ...

如果在分配常量时不需要perl死掉,our声明会变得更简单(可能是my):

our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2);

你可以恢复恒定的性质,同时仍然使用简洁的语法,但有一点魔力:

my $constant = sub {Internals::SvREADONLY($_[$_], 1) for 0 .. $#_};

package Parent;
    $constant->(our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2));

package Child;

# just to demonstrate that anything below can access the constants
sub printAll {
    print "$NO_LEVEL $MY_LEVEL $YOUR_LEVEL\n";  # interpolates :)
}

Child->printAll; # 0 1 2

eval {$NO_LEVEL = 3} or print "error: $@\n";
# error: Modification of a read-only value attempted at ...

您当然可以省略$constant coderef并内联魔术:

package Parent;
    Internals::SvREADONLY($_, 1)
        for our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2);

答案 4 :(得分:2)

继承会影响方法调用($x->m),句点。