Perl Classes :: Не могу записать вывод - PullRequest
1 голос
/ 06 сентября 2011

Я новичок в объектно-ориентированном программировании на Perl.Итак, у меня глупый вопрос.

Что - я пишу скрипт, который будет что-то делать и записывать результат в поток (STDOUT или NETWORK).

Как -

[main.pl]

#!/usr/bin/perl
use strict;

require const::StreamTypes;
require output;

my $out = output->new("output");


$out->writeLine("Sample output");

[output.pm]

#!/usr/bin/perl
use strict;

require const::StreamTypes;

package output;

my $OUTSTR;

sub new{

    my $class   = shift();
    my $stream  = shift();

    if($stream eq const::StreamTypes->STDNET){

    }elsif($stream eq const::StreamTypes->STDWEB){

    }else{
        *OUTSTR = *STDOUT;
    }   

    my $self    = {
        "_outStream"    => $stream,
        "_outStreamPtr" => $OUTSTR
    };

    bless($self, $class);
}

sub writeLine{
    my $msg = shift();
    print(OUTSTR "$msg\n");
}

return 1;

Итак, кто-нибудь может помочь мне понятьчто здесь не так?'CAS программа работает без ошибок, но без вывода.

Спасибо!

Ответы [ 4 ]

2 голосов
/ 06 сентября 2011

Я изменил пару вещей здесь:
первый параметр метода - это сам инвокант (экземпляр или класс)
косвенные файловые дескрипторы являются глобальными!
модуль autodie пригодится, если используется open
подумайте и об использовании в ваших модулях strict

Я бы не рекомендовал использовать глобальную переменную пакета (мой $ OUTSTR;), потому что это может привести к путанице с несколькими экземплярами, которые хотят иметь разные потоки.

И я определенно приобрел привычку использовать аксессоры для всех атрибутов. Вы можете использовать легковесную систему, такую ​​как Class :: Accessor или, возможно, вам даже повезло использовать Moose нашу Mouse . Конечно, есть несколько других модулей, которые по-разному предоставляют средства доступа.

package output;

use strict;
use warnings;
use autodie;

use Class::Accessor "moose-like";

has "outStream" => ( is => 'rw' );

sub new{

    my ( $class, $stream ) = @_;

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

    if ( 0 ) {
        # ...

    } else {
        open( my $outStream, '>&', \*STDOUT );
        $self->outStream( $outStream );
    }

    return $self;
}

sub writeLine{
    my ( $self, $msg ) = @_;
    print { $self->outStream } "$msg\n";
}

return 1;

Moose создаст для вас конструктор, но вы можете вставить обработку параметров так же просто, как показано ниже:

использовать лося;

has "outStream" => ( is => 'rw' );

sub BUILDARGS {
    my ( $class, $stream ) = @_;

    open( my $outStream, '>&', \*STDOUT );

    return {
        outStream => $outStream,
    };
}
0 голосов
/ 07 сентября 2011

Пожалуйста, не используйте голые имена для файловых дескрипторов.Используйте лексические дескрипторы файлов.

В следующих строках предполагается, что где-то есть хеш %type_handlers, который выглядит примерно так:

{ const::StreamTypes->STDNET => \&constructor_for_stdnet_handles
, const::StreamTypes->STDWEB => \&constructor_for_stdweb_handles
}

Затем вы можете заменить нижнюю часть вашего конструктора на

my $handler = $type_handlers{ $stream };
my $outstr  
    = $handler ? $handler->() 
    :            do { my $h; open( $h, '>&', \*::STDOUT ) and $h; }
    ;
return bless( {
      _outStream    => $stream
    , _outStreamPtr => $outstr 
    }
    , $class
    );

Тогда writeLine становится:

sub writeLine { 
    my ( $self, $msg ) = @_;
   ( $self->{_outStreamPtr} || *::STDOUT{IO} )->say( $msg );
}
  • Этот метод немного более надежен в тех случаях, когда кто-то просто благословляет себя в вашем классе.

    my $q_and_d = bless {}, 'output';
    

Если вы не хотите разрешать «быстрые и грязные» экземпляры и хотите получать более точные сообщения о возможных сбоях, вы можете сделать это:

Carp::croak( 'No outstream!' ) 
    unless my $h = Params::Util::_HANDLE( $self->{_outStreamPtr} )
    ;
0 голосов
/ 06 сентября 2011

Как насчет передачи дескриптора файла непосредственно в конструктор объекта?

package output;

sub new {
  my ($class, $fh) = @_;
  bless { file_handle => $fh }, $class;
}

sub writeLine {
  my $self = shift;
  my $line = shift;
  print {$self->{file_handle}} $line;
}

1;

Пример использования:

my $output = output->new(\*STDOUT); # write to stdout

my $socket = IO::Socket::INET->new('www.perl.org', PeerPort => 'http(80)', Proto => 'tcp');
my $output = output->new($socket); # write to a socket
0 голосов
/ 06 сентября 2011

$OUTSTR и *OUTSTR - это очень разные вещи - вы должны выяснить свое недопонимание по этому поводу, прежде чем беспокоиться об объектно-ориентированном программировании.

Тем не менее, вы, вероятно, можете исправить этот скрипт, заставив все ссылаться на $OUTSTR:

...

}else{
    $OUTSTR = *STDOUT;
}

...

print $OUTSTR "$msg\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...