Инициализация объекта в Perl - PullRequest
3 голосов
/ 27 августа 2010

Итак, я немного новичок в Perl. Хотя у меня было что-то гораздо более сложное, я неожиданно наткнулся на контрольно-пропускной пункт и не могу понять, что код не так. Я настолько упростил это, что это всего лишь небольшой фрагмент кода.

Test.pl

package Test;

sub new {
  my ($class) = shift;
  my $self = {
    _attr => "asdfa"
  };
  bless $self, $class;
  return $self;
}
sub log {
  print "\nAccessed via class: ".$self->{_attr};
}

process.pl

#!/usr/bin/perl
do "Test.pl";
use strict;
use warnings;
use diagnostics;

my($test) = new Test();
$test->log;
print "\nAccessed via main: ".$test->{_attr};

Я запускаю process.pl и получаю следующий вывод

Доступ через класс:
Доступ через главный: asdfa

Я также получаю предупреждение

Использование неинициализированного значения в конкатенация (.) или строка в Test.pl строка 12 (# 1) (W не инициализирован) Неопределенное значение использовалось так, как если бы оно уже было определены. Это интерпретировалось как "" или 0, но, возможно, это было ошибкой. Чтобы подавить это предупреждение, назначьте определенное значение вашим переменным.

Так что проблема в том, что $ self на самом деле не определено. Да я понятия не имею. Разве это не способ инициализации объекта?

Ответы [ 3 ]

6 голосов
/ 27 августа 2010

Экземпляр объекта передается в качестве первого аргумента методу. Обычно нужно сохранить его в переменной с именем $self, но perl не устанавливает это для вас, вы должны сделать это самостоятельно:

sub log {
  my $self = shift;
  print "\nAccessed via class: ".$self->{_attr};
}

Обратите внимание, что, хотя вы определили strict и warnings в своем основном коде, вы не указали в test.pl, что означает, что $self был создан в автоматическом режиме с неопределенным значением, а не выдавал ошибку компиляции для использования необъявленная переменная.

Кроме того, я бы посоветовал вам поместить package Test в файл с именем Test.pm, добавить истинное утверждение 1; в конце файла и вызвать его, сказав use Test; вместо do "test.pl". Это гораздо более чистый способ написания модульного кода на Perl.

3 голосов
/ 28 августа 2010

Я знаю, что вы уже приняли ответ, но у вас есть серьезные проблемы с вашим кодом.

  • Поместите определения вашего объекта в файлы, заканчивающиеся на .pm, а не .pl
  • use модулей вместо do ing библиотек.
  • Косвенная запись объектов может привести к ошибкам, лучше избегать ее использования.

Я взялсвобода переписывания вашего кода с небольшими изменениями, необходимыми для устранения проблем.

Сначала в MyTest.pm:

package MyTest;  # Changed name to avoid name conflicts.
use strict;      # Always
use warnings;

sub new {
  my $class = shift;
  # Removed parens on $class, they put the assignment of shift's 
  # result into list context (which had no effect on the result, 
  # but it is also unnecessary).

  my %defaults = ( attr => 'asdfa' );
  my %args = %defaults, @_;  
  # Assigns arguments and default values to %args, actual named 
  # args will override keys in defaults where they match;      

  my $self = {};      

  bless $self, $class;

  while( my ($attr, $value) = each %args ) {
    $self->$attr($value); # Initialize each attribute in named arg hash.
  }

  return $self;
}

sub attr {
    my $self = shift;
    if( @_ ) {
      $self->{_attr} = shift;
    }

    return $self->{attr}
}    

sub log {
  my $self = shift;  # Get invocant
  print "Accessed via class: ", $self->attr, "\n";  
}

process.pl

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

use MyTest;

my $test = MyTest->new();  # Direct call of object constructor

$test->log;

print "Accessed via main: $test->{_attr}\n";  # Violating encapsulation 
                                              # is generally a bad idea.

ЕслиВы делаете тяжелый ООП, подумайте, как научиться использовать Moose .Moose - мощная, ультрасовременная объектная система для Perl, которая добавляет мощные возможности и сокращает стандартный код.

Если вы хотите изучить "классический" Perl OOP, учебники в perldoc ( perlboot , perltoot , perlobj , perlbot и perltooc ) довольно хороши.Если вы хотите углубиться в это, Объектно-ориентированный Perl Дамиана Конвея - фантастическая книга.

0 голосов
/ 27 августа 2010

в под логе:

sub log{
    my $self = shift;
    print "\nAccessed via class: ".$self->{_attr};
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...