Существует ли фактический производный класс во время выполнения в Perl?

Я изучаю Perl OO (новичок в Perl). Я создал тривиальный пример иерархии:
Родительский класс:

#!usr/bin/perl  
use strict;  
use warnings;  

package Objs::Employee;  

my $started;  

sub new {  
    my ($class) = @_;  
    my $cur_time = localtime;  
    my $self = {  
        started => $cur_time,  
    };
    print "Time: $cur_time \n";  
    bless $self;  
}  

sub get_started {  
    my ($class) = @_;  
    return $class->{started};  
}  

sub set_started {  
    my ($class, $value) = @_;  
    $class->{started} = $value;  
}  

1;  

Дочерний класс:

#!/usr/bin/perl  
package Objs::Manager;  
use strict;  
use warnings;  

use base qw (Objs::Employee);  

my $full_name;  

sub new {  
    my ($class, $name) = @_;  
    my $self = $class->SUPER::new();  
    $self->{full_name} = $name;  
    return $self;     
}  

1;  

Я пытаюсь проверить это следующим образом:

#!/usr/bin/perl  
use strict;  
use warnings;  


use Objs::Manager;  

my $emp = Objs::Manager->new('John Smith');  
use Data::Dumper;  
print Dumper($emp); 

Результат:

Время: вс, 29 сентября, 12:56:29 2013 г.

$VAR1 = bless( {
                 'started' => 'Sun Sep 29 12:56:29 2013',
                 'full_name' => 'John Smith'
               }, 'Objs::Employee' );

Вопрос. Почему объект, указанный в дампе, относится к Obj::Employee, а не к Obj::Manager?
Я вызвал new для менеджера.


person Cratylus    schedule 29.09.2013    source источник
comment
Кстати, поскольку методы get_started и set_started являются методами экземпляра (в отличие от new, который является методом класса), первым аргументом для них будет экземпляр класса, а не сам класс. Так что вы должны называть его $self или как-то так, чтобы избежать путаницы.   -  person David Knipe    schedule 29.09.2013
comment
Переменная пакета $started в Objs::Employee не используется.   -  person Alexander Hartmaier    schedule 21.10.2013


Ответы (1)


Всегда используйте два аргумента для bless, так как $class указывает, в какой пакет должен быть благословлен объект. Если $class опущен, используется текущий пакет.

bless $self, $class; 

выход

$VAR1 = bless( {
             'started' => 'Sun Sep 29 13:24:26 2013',
             'full_name' => 'John Smith'
           }, 'Objs::Manager' );

От perldoc -f bless:

Всегда используйте версию с двумя аргументами, если производный класс может наследовать функцию, выполняющую благословение.

person mpapec    schedule 29.09.2013
comment
Почему? Не могли бы вы уточнить? - person Cratylus; 29.09.2013
comment
В моем примере $class - это переданный аргумент, который, как я ожидаю, будет менеджером, поскольку я сделал: Objs::Manager->new. Таким образом, $self, но сам по себе является тем, что возвращает суперконструктор, который является сотрудником, и благословляет его? - person Cratylus; 29.09.2013
comment
Класс всегда является первым параметром в конструкторе (статический метод). При вызове из дочернего класса передается дочерний класс, в противном случае это текущий класс. Обратите внимание, что $class внутри вашего ребенка и родителя - это разные переменные, имеющие разные значения. - person mpapec; 29.09.2013
comment
Даже если $class является Objs::Manager в вызове Objs::Employee->new (что я не оспариваю), это спорный вопрос, потому что вы все равно не использовали $class. Но поскольку вы не использовали второй аргумент для bless, по умолчанию используется текущий пакет, который задается строкой package Objs::Employee;. - person David Knipe; 29.09.2013