2008-11-03 9 views
14

Jak zastosować "use base" w Perlu do dziedziczenia subsów z niektórych modułów bazowych?Jak dziedziczę podprogramy w Perlu za pomocą "podstawy użycia"?

Jestem przyzwyczajony do mechaniki dziedziczenia C++, a wszystkie witryny, do których googlełem, spowodowały więcej zamieszania niż pomocy. Chcę zrobić coś takiego:

#! /usr/bin/perl 
#The base class to inherit from 
use strict; 
use warnings; 

package 'TestBase'; 

#------------------------------- 
sub tbSub 
{ 
    my ($self, $parm) = @_; 
    print "\nTestBase: $parm\n"; 
} 

1; 

.

#! /usr/bin/perl 
#The descendent class 
use strict; 
use warnings; 

use base qw(TestBase); 
sub main; 
sub mySub; 

#------------------------------- 
#Entry point... 
main(); 

#---code------------------------ 
sub main 
{ 
    mySub(1); 
    tbSub(2); 
    mySub(3); 
} 

#------------------------------- 
sub mySub 
{ 
    my $parm = shift; 
    print "\nTester: $parm\n"; 
} 

Perl narzeka/nie może znaleźć tbSub.

Odpowiedz

20

Mechanika C++ niewiele różni się od mechaniki Perla: do dziedziczenia potrzebne są dwie klasy: klasa bazowa i klasa dziedzicząca . Ale nie masz żadnej zstępnej klasy.

Brakuje również konstruktora. W przeciwieństwie do C++, Perl nie zapewni ci domyślnego konstruktora.

Twoja klasa bazowa zawiera zły błąd składni, więc domyślam się, że nie wypróbowałeś kodu przed opublikowaniem.

Wreszcie, jak już zaobserwowano, musisz poinformować Perla, czy chcesz wywołać funkcję, czy wywołać metodę.

Co naprawdę chcesz to wyglądać mniej więcej tak:

my $foo = TestDescendent->new(); 
$foo->main(); 


package TestBase; 

sub new { 
    my $class = shift; 
    return bless {}, $class; 
} 

sub tbSub 
{ 
    my ($self, $parm) = @_; 
    print "\nTestBase: $parm\n"; 
} 

package TestDescendent; 
use base 'TestBase'; 

sub main { 
    my $self = shift; 
    $self->mySub(1); 
    $self->tbSub(2); 
    $self->mySub(3); 
} 

sub mySub 
{ 
    my $self = shift; 
    my $parm = shift; 
    print "\nTester: $parm\n"; 
} 

1; 
4

Dziedziczenie Perla dziedziczy metody, nie działa. Oznacza to, że trzeba będzie zadzwonić

main->tbSub(2); 

Jednak to, co naprawdę chcesz się dziedziczyć metody do właściwej klasy:

package Derived; 
use base "TestBase"; 

package main; 
Derived->somemethod("foo"); 

wywoływanie metod w bieżącym pakiecie jako funkcje nie przejdzie w "Ja" lub "ten" obiekt, a także nazwa klasy magicznie. Wewnętrznie

Class->somemethod("foo") 

zasadniczo kończy się nazywa jak

Class::somemethod("Class", "foo") 

wewnętrznie. Oczywiście zakłada to, że klasa ma podprocedurę/metodę o nazwie "somemethod". Jeśli nie, superklasy klasy zostaną sprawdzone i jeśli nie będą miały metody "somemethod", dostaniesz fatalny błąd. (Ta sama logika dotyczy $ obj-> method ("foo").)

+0

Nie, nie nazywane tak w ten sposób - będzie wyglądać hierarchii dziedziczenia, więc może wywołać sub w zupełnie innej paczce. Również twoje przykłady nie są poprawną składnią. (Wiem, co próbujesz powiedzieć, ale jak to powiedziałeś, jest to konieczne, aby wprowadzić kogoś w błąd tak samo jak PO jeszcze bardziej.) –

+0

Oczywiście chodzi po drzewie dziedziczenia. W końcu chodzi o dziedziczenie. Zauważ, że OP jest używany do dziedziczenia C++, więc pomyślałem, że to będzie oczywiste. – tsee

5

Wydaje mi się, jesteś mieszanie się dwie rzeczy tutaj: obiektowe i proceduralne Perl. Perl OO jest trochę "inny" (jak w głównym nurcie, ale wykonalny).

Twój moduł TestBase.pm wydaje się być uruchamiany jako obiekt Perla (Perl oo-style), ale twój skrypt Perla chce uzyskać do niego dostęp jako "normalny" moduł. Perl nie działa tak, jak robi to C++ (jak sobie uświadomiłeś), więc musiałbyś inaczej skonstruować swój kod. Zobacz książki Damiana Conwaya dla wyjaśnienia (i mądrzejszy kod niż mój poniżej).


proceduralne:

#! /usr/bin/perl 
#The module to inherit from 

package TestBase; 
    use strict; 
    use warnings; 

    use Exporter(); 
    our @ISA   = qw (Exporter); 
    our @EXPORT  = qw (tbSub); 

#------------------------------- 
sub tbSub 
{ 
    my ($parm) = @_; 
    print "\nTestBase: $parm\n"; 
} 

1; 

.

#! /usr/bin/perl 
#The descendent class 
use strict; 
use warnings; 

use TestBase; 
sub main; 
sub mySub; 

#------------------------------- 
#Entry point... 
main(); 

#---code------------------------ 
sub main 
{ 

    mySub(1); 
    tbSub(2); 
    mySub(3); 
} 

#------------------------------- 
sub mySub 
{ 
    my $parm = shift; 
    print "\nTester: $parm\n"; 
} 

Perl OO

#! /usr/bin/perl 
#The base class to inherit from 

package TestBase; 
    use strict; 
    use warnings; 

#------------------------------- 
sub new { my $s={ }; 
    return bless $s; 
} 
sub tbSub 
{ 
    my ($self,$parm) = @_; 
    print "\nTestBase: $parm\n"; 
} 

1; 

.

#! /usr/bin/perl 
#The descendent class 
use strict; 
use warnings; 

use TestBase; 
sub main; 
sub mySub; 

#------------------------------- 
#Entry point... 
main(); 

#---code------------------------ 
sub main 
{ 
    my $tb = TestBase->new(); 
    mySub(1); 
    $tb->tbSub(2); 
    mySub(3); 
} 

#------------------------------- 
sub mySub 
{ 
    my $parm = shift; 
    print "\nTester: $parm\n"; 
} 
5

Jako marginesie, nie ma dobry powód, aby use base zamiast nowsze use parent.

+0

Interesujące. Ale czy istnieje jakiś dobry powód, aby używać rodzica? – innaM

+0

Tak, lepiej przewidzieć, co się stanie. base.pm łączy wiele zachowań i próbuje zgadnąć w niektórych rzadkich okolicznościach. Jest mało prawdopodobne, że napotkasz problemy, które może to spowodować, ale kiedy to zrobisz, to ugryzie. parent.pm nie zawodzi tajemniczo. –

+0

Wystarczająco fair. Dzięki! – innaM

10

Powinieneś rzucić okiem na używanie Moose, który jest postmodernistycznym systemem obiektowym dla Perl5. Prawdopodobnie znajdziesz to o wiele łatwiejsze do uchwycenia niż użycie standardowej Perl OO semantyki ... szczególnie gdy pochodzisz z innego języka OO.

Oto Moose wersja pytanie ....

package TestBase; 
use Moose; 

sub tbSub { 
    my ($self, $parm) = @_; 
    print "\nTestBase: $parm\n"; 
} 


package TestDescendent; 
use Moose; 
extends 'TestBase'; 

sub main { 
    my $self = shift; 
    $self->mySub(1); 
    $self->tbSub(2); 
    $self->mySub(3); 
} 

sub mySub { 
    my ($self, $parm) = @_; 
    print "\nTester: $parm\n"; 
} 


package main; 
my $foo = TestDescendent->new(); 
$foo->main 

Różnice są ....

  • Konstruktor automatycznie utworzone dla Ciebie &
  • dziedziczenia określonej przez "rozciąga" polecenie zamiast "użyj bazy".

Więc ten przykład obejmuje jedynie wierzchołek góry lodowej Moose ;-)

1

składnia OO używa operatora -> oddzielić wiadomość i argumenty z odbiornika wiadomości. Krótka ilustracja poniżej.

+0

Nie ma żadnych ograniczeń w używaniu innych modułów przed 'użyj bazy'. – Ether