2009-09-03 17 views
6

MooseX'i kullanmakta güçlük çekiyorum :: BUILDARGS'i çağırırken doğru şekilde beyan edin.MooseX :: Declare kullanarak bir BUILDARGS yöntemi oluşturmanın doğru yolu nedir?

Bir dosya için bir arabirim olarak bir nesne oluşturmaya çalışıyorum. (Özellikle, dosyadaki sonraki birkaç bayta göz atmamı sağlayan bir ikili dosyaya bir arabirim istiyorum. Daha sonra işlenmek üzere onları devre dışı bırakın.)

Bu gibi nesnelerden birini oluşturabilmek istiyorum

sonra
my $f = binary_file_buffer->new($file_name); 

ve binary_file_buffer sınıf tanımının bu

while(my $block_id = $f->peek($id_offset, $id_length)) { 
    $block_id = unpack_block_id($block_id); 
    $munge_block{ $block_id }->(
     $f->pop($block_size[ $block_id ]) 
    ); 
} 

My gibi kullanmak/bildirisinin bu

use MooseX::Declare; 
class binary_file_buffer { 
    use FileHandle; 
    use Carp; 

    has _file  => (is => 'ro', isa => 'FileHandle'); 
    has _file_name => (is => 'ro', isa => 'Str'); 
    has _buff  => (is => 'rw', isa => 'Str', default => ''); 

    method BUILDARGS (Str $file_name) { 
     my $file = FileHandle->new($file_name); 
     carp "unable to open $file_name : $!" unless defined $file; 
     $file->binmode; 
     return (
     _file_name => $file_name, 
     _file  => $file, 
    ); 
    } 

    # get the next n bytes from the buffer. 
    method pop (Int $len) { 
     # ... Make sure there is data in _buff 
     return substr($self->{_buff}, 0, $len, ''); 
    } 

    # Look around inside the buffer without changing the location for pop 
    method peek (Int $offset, Int $len) { 
     # ... Make sure there is data in _buff 
     return substr($self->{_buff}, $offset, $len); 
    } 
} 
benziyor

(Buraya eklemediğim tampon yükleme ve yönetme kodu var). Oldukça basittir.)

Sorun şu ki, method anahtar kelimesini BUILDARGS bildirgesinde kullanıyorum. Yani, MooseX :: Declare, BUILDARGS'un ilk bağımsız değişkeni olarak nesnesini bekler. Ancak BUILDARGS, argümanları yeni iletilir, bu nedenle ilk argüman dizgisi'binary_file_buffer' paketin adıdır. Sonuç olarak, ilk kod snippet'inde yaptığım gibi yeni bir nesne oluştururken, yazım denetimi başarısız olur. (En azından neler olduğunu benim anlayış.)

alıyorum hata iletisi:

Validation failed for 'MooseX::Types::Structured::Tuple[MooseX::Types::Structured::Tuple[Object,Str,Bool],MooseX::Types::Structured::Dict[]]' failed with value [ [ "binary_file_buffer", "drap_iono_t1.log", 0 ], { } ], Internal Validation Error is: Validation failed for 'MooseX::Types::Structured::Tuple[Object,Str,Bool]' failed with value [ "binary_file_buffer", "drap_iono_t1.log", 0 ] at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 445 
MooseX::Method::Signatures::Meta::Method::validate('MooseX::Method::Signatures::Meta::Method=HASH(0x2a623b4)', 'ARRAY(0x2a62764)') called at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 145 
binary_file_buffer::BUILDARGS('binary_file_buffer', 'drap_iono_t1.log') called at generated method (unknown origin) line 5 
binary_file_buffer::new('binary_file_buffer', 'drap_iono_t1.log') called at logshred.pl line 13 

Ben $ dosya_adi için toz şeker method kelime sarf tür denetlemesini gibi ama bilmiyorum BUILDARGS'dan beri nasıl elde edilir teknik olarak bir yöntem değildir.

Does MooseX :: $self oluşturulmasını atlamanın bir yolu var mı, yoksa böyle bir şey mi?

Bunu doğru şekilde yapıyor muyum MooseX :: Declare way? Yoksa bir şey mi özlüyorum?

cevap

10

İçindekileri ClassName $class olarak tanımladığınız method BUILDARGS (ClassName $class: Str $filename) { ... } gibi bir şey istediğinizi düşünüyorum. Ayrıca

#!/use/bin/perl 

use strict; 
use warnings; 

use MooseX::Declare; 
class BinaryFile::Buffer { 
    use FileHandle; 
    use Carp; 

    has file  => (is => 'ro', isa => 'FileHandle'); 
    has file_name => (is => 'ro', isa => 'Str'); 
    has _buff  => (
     is  => 'rw', 
     isa  => 'Str', 
     default => '', 
     init_arg => undef 
    ); 

    sub BUILDARGS { 
     my ($class, $file_name) = @_; 
     my $file = FileHandle->new($file_name) or do { 
      carp "unable to open ", $file_name, " : $!"; 
      return; 
     }; 
     $file->binmode; 
     return $class->SUPER::BUILDARGS(
       file_name => $file_name, 
       file  => $file 
     ); 
    } 

    # get the next n bytes from the buffer. 
    method pop(Int $len) { 
     # ... Make sure there is data in _buff 
     return substr($self->buff, 0, $len, ''); 
    } 

    # Look around inside the buffer without changing the location for pop 
    method peek(Int $offset, Int $len) { 
     # ... Make sure there is data in _buff 
     return substr($self->buff, $offset, $len); 
    } 
} 

my $f = BinaryFile::Buffer->new($0); 

print $f->file_name, "\n"; 
+1

Bingo! Tam olarak istediğimi yapar. Dokümanlarınızdaki yanıtlarınızı açıklığa kavuşturdum. İlk olarak, Moose :: Manual :: Types belgelerinde ClassName alt türü Str görmedim. ClassName dize alt türünde yerleşik beklemiyordum. İkincisi, MooseX :: Method :: Signatures belgelerinin nasıl bir yöntemin nasıl isimlendirileceğini ve türünün nasıl olduğunu göstermediğini görmedim. MooseX :: Declare kullanımlarının MooseX :: Method :: Signatures paketinden geldiği yöntem imza sözdizimini anlamadım. Şimdiye kadar, MooseX :: Declare'yi seviyorum. İstediğimi yapmak için bir Moose yolu olduğunu biliyordum. Sadece nasıl olduğunu anlayamadım. Teşekkürler. – meta4

+0

Nesne yerine ClassName'i yöntem/etrafında kullanmak MooseX :: Declare el kitabında gerçekten bir yere yazılmalıdır. – anydot

2

İstediğin düşünüyorum Eğer aramazsan o özen FileHandle-> yeni ($ dosya_adı),

ama

FileHandle->new(
_filename => $file_name 
); 
(normal sözdizimi olan)

,

hala işe yarar!Ayrıca

, siz (diğer durumlarda dosya adları için ancak bu kadar kullanışlı değil) olabilir

bir

multi method (ClassName $class, Int $some_number){} 

bu şekilde eklemek, şimdi hashrefs, tamsayılar ve dizeleri ele verebilir yeni ...

olasılıklar ...;)

1

(benden önce cevap sadece bir genişleme) bunu yapmanın oldukça düzgün bir yol::, MooseX :: MultiMethods olacak

use MooseX::MultiMethods; 

multi method BUILDARGS (ClassName $class: Str $filename) { 

#do whatever you want to do if only a strg is passed 

} 

bu şekilde

İlgili konular