2011-10-19 20 views
6

więc szło o mojej działalności Moosey i myślałem, hej może być ładne użyć stałej w tych miejscach, w których używam numerów, aby było jasne, co te liczby oznaczają albo w przypadku gdy późniejDlaczego podklasa nie dziedziczy stałych rodzica?

Więc zmienić w klasie nadrzędnej dodałem standardową "stałą użycia"

, ale klasa podrzędna nie jest świadoma stałych ustawionych w rodzicu! doh!

Zgaduję, że muszę zrobić trochę magii Łosia, żeby to zadziałało prawidłowo, lub coś zupełnie innego. Moje wyszukiwanie w tej sprawie nie przyniosło żadnych wyników =/

Odpowiedz

3

Ponieważ stałe są podprogramami i można uzyskać dziedziczenie, nazywając je metodami bit został już pokryty śmiercią, tutaj jest inny spin na rzeczy.

Jeśli wiesz, że pracują tylko w jednym pliku, można używać stałych leksykalnych do pakietów mostowych:

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 ... 

Jeśli nie trzeba Perl umrzeć podczas przypisywania do stałej, deklaracja our dostaje nieco prostsze (i może być my):

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

można przywrócić stały charakter, a jednocześnie przy użyciu składni lakoniczny z odrobiną magii:

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 ... 

Można oczywiście pominąć $constant coderef i inline magię:

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

+1 za kompletną odpowiedź. To naprawdę pomogło mi zrozumieć sytuację tutaj. Dziękuję Eric! – qodeninja

10

Stałe są podprogramami.

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

Należy pamiętać, że stałe są podprogramy z pustym prototypu. perl wykorzystuje to do wstawiania ich podczas kompilacji. Jednak wywołania metod pomijają prototypy, a zatem dziedziczne stałe dostępne w ten sposób nie zostałyby przedstawione.

+0

Dlaczego umieścić zewnętrzna {} na opakowaniu?Zacząłem to robić, a ktoś mnie pospieszył, że to nie było konieczne. p.s. Chciałbym uzyskać dostęp do stałych bezpośrednio w klasie potomnej, więc wygląda na to, że muszę użyć $ self-> CONSTANT right? – qodeninja

+1

@ nodebunny Zawarłem pakiety w zakresie, ponieważ wszystko to znajduje się w jednym pliku. Ponieważ to są dane klasowe, chciałbym to wyraźnie powiedzieć. '$ self-> CONSTANT' będzie działać, oczywiście. –

+0

interesujące, wydaje się, że jest to idel. znowu nie miałem jeszcze pomysłu na bloki. {} <== jest blokiem tak? +1 dla pełnego przykładu. – qodeninja

4

Nazwij je jako metodę.

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

+1 dla pierwszego wyjaśnienia $ self-> constant – qodeninja

6

to faktycznie wymienione w documentation, choćby mimochodem:

„Stałe należą do pakietu są zdefiniowane w celu odnoszą się do stałej zdefiniowanej w innym opakowaniu, należy określić w pełni. nazwa pakietu, jak w Some::Package::CONSTANT. Stałe mogą być eksportowane przez moduły i mogą być również wywoływane jako metody klasy lub instancji, tj. jako Some::Package->CONSTANT lub jako $obj->CONSTANT, gdzie $obj jest instancją Some::Package. Podklasy mogą definiować własne stałe do nadpisania w swojej klasie bazowej. "

+0

, więc mogę zrobić Parent :: CONSTANT too eh? Myślę, że lepiej to lubię. Szukałem w dokumentach CPAN/Moose, myśląc, że istnieje sposób na Moose'a, ale to też działa. +1 dla dokumentu – qodeninja

+0

'Parent :: CONSTANT' nie pozwala na przesłonięcie go w klasach potomnych. Wszystko zależy od tego, czego chcesz. –

+1

@Sinan: Z drugiej strony 'Parent :: CONSTANT' ma tę zaletę, że można go rozwiązać w czasie kompilacji. –

2

Dziedziczenie wpływa na wywołania metod ($x->m), kropka.

+0

+1 za bycie wiecznym ikegami – qodeninja

Powiązane problemy