2015-06-18 2 views
0

Я пытаюсь изучить наследование в Perl.perl наследование и структура каталогов

Это моя структура каталогов:
perldir
perldir \ child.pl
perldir \ MYLIB
perldir \ MYLIB \ Parent.pm

Parent.pm

package Parent; 

sub new { 
    my $class = shift; 
    my $self = { _first => shift, _last => shift }; 
    bless $self, $class; 
} 

sub getFirstName { 
    my ($self) = @_; 
    return $self->{ _first }; 
} 

1; 

child.pl

package Child; 

use parent 'Mylib::Parent'; 

sub new { 
    my $class = shift; 
    my $self = Parent->new(shift, shift); 
    bless $self, $class; 
} 

my $obj = new Child('Jack', 'Sparrow'); 
print $obj->{_first},' ',$obj->{_last}; 
print "\n",$obj->getFirstName(); #Error 

Ошибка, наложенная на последнюю строку: Не удается найти метод объекта «getFirstName» через пакет «AChild» в строке child.pl 13;

Программа работает, если я выполняю одно из следующих действий:
1. У меня есть оба файла в каталоге Mylib.
2. заменяет

use parent 'Mylib::Parent' 

с

use Mylib::Parent; 
@ISA = ('Parent'); 

Можно ли получить программу для работы с помощью «использовать родитель» и с классом ребенка в другом каталоге?

==========================
ОБНОВЛЕНО вопрос основанный на ответ choroba «s.

Ok я изменил классы, чтобы отразить следующее:

Parent.pm

package Mylib::Parent; 

sub new { 
    my $class = shift; 
    my $self = { _first => shift, _last => shift }; 
    bless $self, $class; 
} 

sub getFirstName { 
    my ($self) = @_; 
    return $self->{ _first }; 
} 

1; 

child.pl

package Child; 

use parent 'Mylib::Parent'; 

sub new { 
    my $class = shift; 
    my $self = Mylib::Parent->new(shift, shift); 
    bless $self, $class; 
} 

my $obj = new Child('Jack', 'Sparrow'); 
print $obj->{_first},' ',$obj->{_last}; 
print "\n",$obj->getFirstName(); 

выше работает отлично. Теперь рассмотрим, что я хочу, чтобы другой дочерний класс находился в том же каталоге, что и Parent.pm.

perldir \ MYLIB \ ChildTwo.pl

package ChildTwo; #or package Mylib::ChildTwo; 

use parent 'Mylib::Parent'; #or use parent 'Parent'; 

sub new { 
    my $class = shift; 
    my $self = Mylib::Parent->new(shift, shift); #or Parent->new(shift, shift); 
    bless $self, $class; 
} 

my $obj = new ChildTwo('Jack', 'Sparrow'); #or new Mylib::ChildTwo('Jack','Sparrow'); 
print $obj->{_first},' ',$obj->{_last}; 
print "\n",$obj->getFirstName(); 

1; 

выше не работает. Могу ли я заставить ChildTwo.pl работать вместе с Child.pl без использования 'use lib'?

+0

'Parent' ne 'AParent'. – choroba

+0

Если это дочерний класс, он должен перейти к файлу pm, а не к pl. – choroba

+0

Я понимаю соглашения. Я пытаюсь понять, как заставить оба .pl работать с тем же Parent.pm – raka

ответ

0

Моя цель была, чтобы понять, как классы могут использовать друг друга, когда они проживали в разных пакетах. Похоже, в отличие от Java, где «lib» обычно означает сторонние банки, lib в Perl обозначает корень, содержащий все пакеты, специфичные для скрипта.

Похоже 'потребительной Lib (dirpath)' должен быть использован. См. Использование в ChildThree.pm.

Структура каталогов:

/perldir/child.pl
/perldir/use_child_two.pl
/perldir/use_child_three.pl
/perldir/Mylib/Parent.pm
/perldir/MYLIB/ChildTwo.pm
/perldir/Secondlib/ChildThree.pm

/perldir/Mylib/Parent.pm

package Mylib::Parent; 

sub new { 
    my $class = shift; 
    my $self = { _first => shift, _last => shift }; 
    bless $self, $class; 
} 

sub getFirstName { 
    my ($self) = @_; 
    return $self->{ _first }; 
} 

1; 

/perldir/child.pl

package Child; 

use parent 'Mylib::Parent'; 

sub new { 
    my $class = shift; 
    my $self = Mylib::Parent->new(shift, shift); 
    bless $self, $class; 
} 

my $obj = new Child('Jack', 'Sparrow'); 
print $obj->{_first},' ',$obj->{_last}; 
print "\n",$obj->getFirstName(); 

/perldir/Mylib/ChildTwo.pm

package Mylib::ChildTwo; 

use parent 'Mylib::Parent'; 

sub new { 
    my $class = shift; 
    my $self = Mylib::Parent->new(shift, shift); 
    bless $self, $class; 
} 

1; 

/perldir/use_child_two.pl

use Scalar::Util ('blessed'); 

use Mylib::ChildTwo; 

my $obj = new Mylib::ChildTwo('Jack', 'Sparrow'); 
print "\n Class: ", blessed ($obj); 
print "\n ",$obj->{_first},' ',$obj->{_last}; 
print "\n ",$obj->getFirstName(); 

1; 

/perldir/Secondlib/ChildThree.pm

package Secondlib::ChildThree; 

use lib '/perldir';  #Adds directories to search path to discover 
         #package structure and finding module 'Mylib::Parent' 
use parent 'Mylib::Parent'; 

sub new { 
    my $class = shift; 
    my $self = Mylib::Parent->new(shift, shift); 
    bless $self, $class; 
} 

1; 

/perldir/use_child_three.пл

use Scalar::Util ('blessed'); 

use Secondlib::ChildThree; 

my $obj = new Secondlib::ChildThree('Jack', 'Sparrow'); 
print "\n Class: ", blessed ($obj); 
print "\n ",$obj->{_first},' ',$obj->{_last}; 
print "\n ",$obj->getFirstName(); 

1; 
+1

Вы можете использовать несколько 'lib'. – choroba

3

Вы должны сделать свой ум: либо имя родительского пакета является Parent, то в child.pl:

use parent 'Parent'; 

и сказать Perl, где искать его:

perl -IMylib child.pl 

или использовать lib

use FindBin; 
use lib "$FindBin::Bin/Mylib"; 

Или, адрес доставки: Mylib::Parent, то вы должны исправить объявление пакета:

package Mylib::Parent; 

и вызвать правильный конструктор:

my $self = Mylib::Parent->new(shift, shift); 
0

Вы не должны использовать package в обычных сценариев Perl по умолчанию. Объявление package используется для создания нового пространства имен для предотвращения именования коллизий между модулями.

Для простоты вам не нужно создавать каталоги модулей для определения пакетов. На самом деле, в объектно-ориентированном Perl не редкость определять ваши классы в вашей основной программе, если они не будут использоваться совместно с другими программами.

Вот пример простого наследования. Я создаю два объекта . $wife является классом Person, а $me является подклассом лица под названием Developer. Обратите внимание на то, что у меня нет new или name Подпрограммы ..Я имею в виду .. методы, определенные в моем Developer классе. Те, что унаследованы моим заявлением use parent -norequire qw(Person);.

#! /usr/bin/env perl 

use strict; 
use warnings; 
use feature qw(say); 
use Data::Dumper; 

my $wife = Person->new(); 
$wife->name("Susan"); 
$wife->occupation("Quantum Physicist"); 

say "Name: " . $wife->name; 
say "Occupation: " . $wife->occupation . "\n"; 

my $me = Developer->new("Bob"); 
$me->programming_language("Perl"); 

say "Name: " . $me->name; 
say "Language: " . $me->programming_language; 

######################################################################## 
######################################################################## 

package Person; 

sub new { 
    my $class   = shift; 
    my $name   = shift; 
    my $occupation  = shift; 

    my $self = {}; 
    bless $self, $class; 

    $self->name($name); 
    $self->occupation($occupation); 
    return $self; 
} 

sub name { 
    my $self   = shift; 
    my $name   = shift; 

    if (defined $name) { 
     $self->{NAME} = $name; 
    } 
    return $self->{NAME}; 
} 

sub occupation { 
    my $self   = shift; 
    my $occupation  = shift; 
    if (defined $occupation) { 
     $self->{OCCUPATION} = $occupation; 
    } 
    return $self->{OCCUPATION}; 
} 

package Developer; 
use parent -norequire, qw(Person); 

sub programming_language { 
    my $self   = shift; 
    my $language  = shift; 

    if (defined $language) { 
     $self->{LANGUAGE} = $language; 
    } 

    return $self->{LANGUAGE}; 
} 

Можно использовать SUPER класс, чтобы заставить ваш подкласс использовать суперкласс определения:

Я мог бы определил new подпрограммы ... ээ ... методом ,. ..no, э-э ... конструктор в моем классе Developer тоже:

package Developer; 

... 

sub new { 
    my $class   = shift; 
    my $name   = shift; 
    my $language  = shift; 
    my $occupation  = "Code Slinger"; 

    my $self = {}; 
    bless $self, $class;  # Defines a Developer or subclass object 

    $self->SUPER::name($name); # Sets the name of my Developer 
    $self->SUPER::occupation($occupation); # We know the occupation 
    return $self; 
} 

Теперь, если я попрошу $me->occupation, он вернется Code Slinger.

Смежные вопросы