的Perl类::无法写入输出

问题描述:

我是新来的对象在Perl的面向对象编程。所以,我有一个愚蠢的问题。的Perl类::无法写入输出

什么 - 我写一个脚本,将做一些事情,结果写入流(标准输出或网络)。

如何 -

[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; 

因此,谁能帮助我明白是怎么回事错在这里? '程序运行没有错误,但没有输出。

谢谢!

+0

目前还不清楚是什么你正在努力实现?我可以运行程序,将所有对const :: StreamTypes的引用剥离出来,并打印出对象:'output = HASH(0x7fbfcb004038)'。你可能希望writeLn有一个'my($ self,$ msg)= @_;'行而不是'shift'? – Unk

$OUTSTR*OUTSTR是非常不同的事情 - 在担心面向对象编程之前,您应该清除对此的误解。

这就是说,你或许可以让一切来指$OUTSTR解决这个脚本:

... 

}else{ 
    $OUTSTR = *STDOUT; 
} 

... 

print $OUTSTR "$msg\n"; 
+0

感谢您的回复。我当然会研究它,但是当我按照你的建议更改了代码后,得到如下输出: 'output = HASH(0x100834c20)' –

怎么样正好路过一个文件直接处理到对象的构造?

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

我希望输出模块能够处理低级细节。但你的建议看起来很有趣...... –

我改变了一些东西在这里:
the first parameter of a methd is the invocant (instance or class) itself
indirect file handles are globals!
the autodie module comes in handy, if using open
consider using strict in your modules, too

我不会推荐使用包全局的变量(my $ 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; 

穆斯将创建一个构造你,但你可以将你的参数处理容易如下:

使用驼鹿;

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

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

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

    return { 
     outStream => $outStream, 
    }; 
} 
+0

+1:像使用驼鹿和干净的改写。 –

请不要使用文件句柄的裸号。使用词法文件句柄。

以下行假设有一个散列%type_handlers的地方,看起来是这样的:

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变为:

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

然后你就可以将其替换你的构造函数的底部:

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}) 
    ;