Переменные Perl OO Superclass не привязываются к объекту подкласса при печати - PullRequest
2 голосов
/ 02 июля 2010

Я делаю пример Perl OO (главным образом для повторного знакомства с Perl) и использую наследование. Кажется, что SUPER работает в подклассе при вызове конструктора суперкласса и что переменные суперкласса не привязываются к объекту подкласса.С чего бы это?

################################################
## Package : Person                          ##
################################################
package Person;

################################################
## Constructor                                ##
################################################
sub new(){

    my $class = shift;
    my $data = {};
    $data->{'firstName'} = shift;
    $data->{'secondName'} = shift;  
    bless $data, $class; 
    #bless $data, "Person"; #hack
    return $data;
}

################################################
## Getter Methods                            ##
################################################

sub getFirstName(){
  my $data = shift;
  return $data->{'firstName'};
}

sub getSecondName(){
  my $data = shift;
  return $data->{'secondName'};
}

################################################
## Setter methods                            ##
################################################

sub setFirstName($){
  my $data = shift;
  $data->{'firstName'} = shift;
}

sub setSecondName($){
  my $data = shift;
  $data->{'secondName'} = shift;
}

################################################
## Other Methods                              ##
################################################

sub printall(){
    my $data = shift;
    $\ = "\n";
    print "FirstName: ". $data->{'firstName'} ."\n";
    print "SecondName: ". $data->{'secondName'} ."\n";
}
1;

################################################
## Package : Coder                            ##
################################################

package Coder;
@ISA = qw( Person );
use strict;
use warnings;

################################################
## Constructor                                ##
################################################
sub new {
    my $class = shift;
    my $self = {};

    bless $self, $class;
    my $superFirstName = shift;
    my $superSecondName = shift;

    print "new superfirstname "  .$superFirstName;
    print "new supersecondname " .$superSecondName; 

    $self->{'language'} = shift; #i.e. Java 
    $self->{'experience'} = shift;  #number of years

    #$self = $self->SUPER::new($superFirstName, $superSecondName); 
    Person->new($superFirstName, $superSecondName);
    return $self;
}

################################################
## Getter Methods                            ##
################################################

sub getLanguage(){
  my $data = shift;
  return $data->{'language'};
}

sub getExperience(){
  my $data = shift;
  return $data->{'experience'};
}

################################################
## Setter methods                            ##
################################################

sub setLanguage($){
  my $data = shift;
  $data->{'language'} = shift;
}

sub setExperience($){
  my $data = shift;
  $data->{'experience'} = shift;
}

################################################
## Other Methods                              ##
################################################

sub printall(){
    my $data = shift;
    $\ = "\n";

    print "Experience: " . $data->{'experience'};
    print "Language: " . $data->{'language'};

    $data->SUPER::printall();

}
1;


################################################
## Package : Main                            ##
################################################
package main;

my $developer = Coder->new("John","Smith","Perl","2");

$developer->printall();

Ответы [ 3 ]

3 голосов
/ 02 июля 2010

Это потому, что вы ничего не делаете с возвратом Person->new. Таким образом, он просто создает целый другой Person объект, и Coder счастливо катается.

То, что вы хотите сделать, это

my $self = $class->SUPER::new( $superFirstName, $superSecondName );

И пусть Person благословит его в любом классе, который вы передаете, - как он это делает. Затем, после создания $self способа SUPER, вы хотите добавить в него нужные вам поля.

Так это должно выглядеть примерно так:

use strict;
use warnings;

sub new {
    my $class = shift;
    my $superFirstName = shift;
    my $superSecondName = shift;
    print "new superfirstname "  .$superFirstName;
    print "new supersecondname " .$superSecondName; 

    my $self = $class->SUPER::new( $superFirstName, $superSecondName );
    # OR
    # $self = $class->Person::new( $superFirstName, $superSecondName );

    $self->{language}   = shift; #i.e. Java 
    $self->{experience} = shift;  #number of years

    return $self;
}
3 голосов
/ 02 июля 2010

Если вы намереваетесь, что Coder наследует от Person, вы неправильно его конструируете.Например, в конструкторе Coder вы создаете новый объект Person, а затем выбрасываете его.Это был бы намного лучший (и более стандартный) способ создания объекта Coder, который наследуется от Person (см. perldoc perltoot ):

sub new
{
    my $class = shift;
    my $this = $class->SUPER::new(shift, shift);

    # add on extra fields, now at the head of @_...

    bless $this, $class;
    return $this;
}

Также можно сделать много улучшений.:

  • отсутствует use strict; use warnings; лично
  • use parent 'Person';, а не манипулирует прототипами функций @ ISA
  • редко - хорошая идея (используйте их, только если вы знаю они вам нужны, и это никогда верно при написании объектно-ориентированного класса, где функции будут вызываться как методы)
  • вы можете автоматически генерировать методы доступа и мутаторы с помощью Class :: Accessor , вместо того, чтобы писать много дублирующихся шаблонов

Кроме того, хотя я не уверен, что вы готовы (вы должны понимать основы построения Perl OOво-первых), вы можете пропустить написание почти всего этого кода, используя Moose :

package Person;
use Moose;
has [qw(firstName secondName)] => (
    is => 'rw', isa => 'Str',
);
no Moose;
__PACKAGE__->meta->make_immutable;
1;

package Coder;
use Moose;
extends 'Person';
has [qw(language experience)] => (
    is => 'rw', isa => 'Str',
);
no Moose;
__PACKAGE__->meta->make_immutable;
1;
2 голосов
/ 02 июля 2010

Конструктор для Coder не имеет смысла;Вы звоните Person->new, а затем отбрасываете результат.Вот более полезный шаблон:

package Coder;

sub new {
  my $class = shift;

  my $self = $class->SUPER::new(shift, shift); # firstname, lastname

  $self->{language} = shift;
  $self->{experience} = shift;

  $self;
}

Да, конструктор Person благословит объект в Coder в этом случае, а не в Person - в этом и заключается смысл иметь класс в качествеПервый аргумент для new.

Это версия вашего кода с минимальными изменениями, но я хотел бы сделать несколько дополнительных предложений:

  1. ПозиционныйПараметры конструктора - отличный способ убедиться, что никто не знает, что происходит.Я бы посоветовал набрать его как Person->new(first_name => "Joe", last_name => "Random") и т. Д.

  2. Возможно, вам лучше забыть обо всей этой работе, используя Moose :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...