2011-09-06 65 views
1

我是新來的對象在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

回答

0

$OUTSTR*OUTSTR是非常不同的事情 - 在擔心面向對象編程之前,您應該清除對此的誤解。

這就是說,你或許可以讓一切來指$OUTSTR解決這個腳本:

... 

}else{ 
    $OUTSTR = *STDOUT; 
} 

... 

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

感謝您的回覆。我當然會研究它,但是當我按照你的建議更改了代碼後,得到如下輸出: 'output = HASH(0x100834c20)' –

0

怎麼樣正好路過一個文件直接處理到對象的構造?

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

我希望輸出模塊能夠處理低級細節。但你的建議看起來很有趣...... –

2

我改變了一些東西在這裏:
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:像使用駝鹿和乾淨的改寫。 –

0

請不要使用文件句柄的裸號。使用詞法文件句柄。

以下行假設有一個散列%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}) 
    ;