6

BUILDARGSを呼び出すときに、MooseX::Declareを正しく使用できません。

ファイルのインターフェイスとしてオブジェクトを作成しようとしています。(具体的には、ファイル内の次の数バイトを確認し、さらに処理するためにそれらを切り落とすことができるバイナリファイルへのインターフェイスが必要です。)

このようなオブジェクトの1つを作成できるようにしたい

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

そして、このように使用します

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

私のbinary_file_bufferクラスの定義/宣言は次のようになります

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

(ここに含めなかったコードのバッファーのロードと管理があります。これはかなり簡単です。)

method問題は、BUILDARGS宣言でキーワードを使用していることです。したがって、MooseX :: Declareは、の最初の引数としてbinary_file_buffer オブジェクトBUILDARGSを想定しています。ただしBUILDARGS、引数はnewに渡されるため、最初の引数は文字列a'binary_file_buffer'であり、パッケージの名前です。その結果、最初のコードスニペットで行ったように、newを使用してオブジェクトを作成すると、型チェックに失敗して終了します。(少なくとも、それが何が起こっているのかについての私の理解です。)

私が受け取るエラーメッセージは次のとおりです。

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

キーワードが$file_nameに提供する型チェックシュガーが好きですが、技術的にはメソッドではないmethodため、取得方法がわかりません。BUILDARGS

MooseX :: Declareには、$self作成をスキップする方法などがありますか?

私はこれを適切なMooseX::Declareの方法で行っていますか?それとも私は何かが足りないのですか?

4

3 に答える 3

10

method BUILDARGS (ClassName $class: Str $filename) { ... }呼び出し元を明示的に定義するようなものが必要だと思いますClassName $class

于 2009-09-03T04:09:18.187 に答える
2

私はあなたが欲しいと思います:

#!/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";
于 2009-09-03T04:22:18.597 に答える
1

また、それを行うための本当にきちんとした方法(私の前の答えの単なる拡張):

use MooseX::MultiMethods;

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

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

}

そうすれば、MooseX :: MultiMethodsは、FileHandle-> new($ file_name)を呼び出さない場合に注意を払います。

しかし

FileHandle->new(
_filename => $file_name
);

(これは通常の構文です)、

それでも動作します!

また、可能性があります(これはファイル名にはあまり役立ちませんが、他の場合には)

追加する

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

そうすれば、newはハッシュ参照、整数、文字列を処理できるようになります...

ああ可能性...;)

于 2009-11-02T01:02:08.620 に答える