2011-10-19 122 views
6

所以我會約我MOOSEY業務,我想,嘿可能是不錯的使用在這些地方爲常數,且我使用的號碼,要清楚這些數字的含義或情況下,他們改變後爲什麼子類不能繼承父類的常量?

所以在父類中我加入了標準的「使用常量」

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; 
} 

但孩子上課不知道在父母設定的常量!衛生署!

我猜我必須做一些駝鹿魔術才能讓這個工作正常,或完全是其他的東西。我在這個問題上搜索沒有取得任何結果=/

回答

3

由於常量是子程序,您可以通過調用它們作爲方法位已被覆蓋到死亡繼承,這是一個不同的東西。

如果你知道你只在一個文件時,您可以使用詞彙常量橋包:

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: [email protected]\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: [email protected]\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); 
+0

+1爲一個完整的答案。這真的幫助我瞭解這裏的情況。謝謝埃裏克! – qodeninja

10

常量是子例程。

{ 
    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利用這個在編譯期間將它們內聯。然而,方法調用忽略原型,因此以這種方式訪問​​的可繼承常量不會被內聯。

+0

?我開始這樣做,有人嘲笑我說沒有必要。附:我想直接在子類中訪問常量,所以它看起來像我必須使用$ self> CONSTANT正確嗎? – qodeninja

+1

@nodebunny我把這些包放在一個範圍內,因爲所有這些都在一個文件中。由於這是班級數據,我喜歡明確說明。顯然,'$ self-> CONSTANT'會起作用。 –

+0

有趣,這看起來像一個Perl的成語。然後我還沒有真正瞭解塊的想法。 {} <==是塊是啊? +1的全部例子。 – qodeninja

4

稱它們爲一種方法。

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

+1首先解釋$ self->常量 – qodeninja

6

這實際上是在documentation如果只是順便提到,:

「常量屬於它們在定義的包要引用另一個包中定義的常數,指定完整。軟件包名稱,如Some::Package::CONSTANT。常量可以由模塊導出,也可以作爲類或實例方法調用,即Some::Package->CONSTANT$obj->CONSTANT其中$objSome::Package的實例。子類可以定義它們自己的常量以覆蓋那些在他們的基礎階層。「

+0

所以我可以做Parent :: CONSTANT也是呃?我覺得我更喜歡那樣。我正在尋找CPAN/Moose文檔,認爲這有一個駝鹿的方式來做到這一點,但這也起作用。 +1爲文檔 – qodeninja

+0

「Parent :: CONSTANT」不允許您在子類中覆蓋它。這一切都取決於你想要的。 –

+1

@Sinan:另一方面,'Parent :: CONSTANT'確實具有可以在編譯時解決的優點。 –

2

繼承影響方法調用($x->m),句點。

+0

+1僅用於永恆ikegami – qodeninja

相關問題