的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;
因此,谁能帮助我明白是怎么回事错在这里? '程序运行没有错误,但没有输出。
谢谢!
$OUTSTR
和*OUTSTR
是非常不同的事情 - 在担心面向对象编程之前,您应该清除对此的误解。
这就是说,你或许可以让一切来指$OUTSTR
解决这个脚本:
...
}else{
$OUTSTR = *STDOUT;
}
...
print $OUTSTR "$msg\n";
感谢您的回复。我当然会研究它,但是当我按照你的建议更改了代码后,得到如下输出: '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
我希望输出模块能够处理低级细节。但你的建议看起来很有趣...... –
我改变了一些东西在这里:
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,
};
}
+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})
;
目前还不清楚是什么你正在努力实现?我可以运行程序,将所有对const :: StreamTypes的引用剥离出来,并打印出对象:'output = HASH(0x7fbfcb004038)'。你可能希望writeLn有一个'my($ self,$ msg)= @_;'行而不是'shift'? – Unk