2009-09-03 14 views
6

मुझे MooseX का उपयोग करने में कठिनाई हो रही है :: BUILDARGS को कॉल करते समय ठीक से घोषित करें।MooseX :: घोषणा का उपयोग कर BUILDARGS विधि बनाने का उचित तरीका क्या है?

मैं एक फ़ाइल के लिए एक इंटरफेस के रूप में एक वस्तु बनाने की कोशिश कर रहा हूं। (विशेष रूप से, मैं एक बाइनरी फ़ाइल के लिए एक इंटरफ़ेस चाहता हूं जो मुझे फ़ाइल में अगले कुछ बाइट्स पर देखने देता है और फिर आगे प्रसंस्करण के लिए उन्हें बंद कर देता है।)

मैं इन वस्तुओं में से एक को बनाने में सक्षम होना चाहता हूं जैसे

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); 
    } 
} 
तरह लग रहा है

(बफर लोडिंग और प्रबंधन कोड है जिसमें मैंने यहां शामिल नहीं किया था। यह काफी सीधे आगे है।)

समस्या यह है कि, मैं BUILDARGS घोषणा में कीवर्ड method का उपयोग करता हूं। तो, MooseX :: घोषित binary_file_bufferऑब्जेक्टBUILDARGS के पहले तर्क के रूप में घोषित करता है। लेकिन BUILDARGS तर्कों को नए पास कर दिया गया है, इसलिए पहला तर्क स्ट्रिंग'binary_file_buffer', पैकेज का नाम है। नतीजतन यह नई जांच का उपयोग करते समय ऑब्जेक्ट बनाने के दौरान प्रकार की जांच में विफल रहता है और मर जाता है, जैसे मैंने पहले कोड स्निपेट में किया था। (कम से कम है कि क्या हो रहा है की मेरी समझ है।)

त्रुटि संदेश मैं मिलता है:

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 :: घोषित करने के लिए $self निर्माण को छोड़ने का कोई तरीका है, या ऐसा कुछ?

क्या मैं इसे उचित MooseX :: घोषित कर रहा हूं? या क्या मैं कुछ न कुछ भूल रहा हूं?

उत्तर

10

मुझे लगता है कि आप method BUILDARGS (ClassName $class: Str $filename) { ... } जैसे कुछ चाहते हैं जिसमें आप स्पष्ट रूप से Invocant को ClassName $class के रूप में परिभाषित करते हैं।

+1

बिंगो! यह वही करता है जो मैं चाहता हूं। मुझे आपकी प्रतिक्रिया स्पष्ट करने वाले दस्तावेज़ों में 2 चीजें याद आईं। सबसे पहले, मुझे क्लासनाम क्लासनाम उप प्रकार के स्ट्रोज में नहीं देखा गया :: मैनुअल :: प्रकार दस्तावेज़। मैं क्लासनाम स्ट्रिंग उप प्रकार में निर्मित की उम्मीद नहीं कर रहा था। दूसरा, मुझे MooseX नहीं देखा गया :: विधि :: हस्ताक्षर दस्तावेज़ दिखाते हैं कि किसी विधि के आक्रमणकर्ता को कैसे नाम दें और इसके प्रकार की घोषणा कैसे करें। मुझे विधि हस्ताक्षर वाक्यविन्यास का एहसास नहीं हुआ कि MooseX :: घोषणा का उपयोग MooseX :: विधि :: हस्ताक्षर पैकेज से है। अब तक, मुझे MooseX :: घोषित करना पसंद है। मुझे पता था कि जो कुछ मैं चाहता था उसे करने के लिए एक मूस रास्ता था। मैं बस कैसे पता नहीं लगा सका। धन्यवाद। – meta4

+0

विधि/आस-पास के ऑब्जेक्ट के बजाय कक्षा नाम का उपयोग करना वास्तव में MooseX के मैनुअल में लिखा जाना चाहिए :: घोषित करें ... इसके द्वारा भी काटा गया – anydot

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"; 
1

भी यह (सिर्फ एक मेरे सामने जवाब के विस्तार) करने का एक वास्तव में साफ रास्ता:

use MooseX::MultiMethods; 

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

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

} 

कि जिस तरह से, MooseX :: मुल्टीमेथड्स होगा ध्यान रखना है कि यदि आप कॉल नहीं करते FileHandle-> नई ($ file_name),

लेकिन

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

(जो सामान्य वाक्यविन्यास है),

यह अभी भी काम करेगा!

इसके अलावा, आप कर सकते थे (जो फ़ाइल नामों के लिए लेकिन अन्य मामलों में तो उपयोगी नहीं है)

एक

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

कि जिस तरह से जोड़ने के लिए, नया अब hashrefs ने पूर्णांक और तार संभाल सकता ...

ओह संभावनाएं ...;)

संबंधित मुद्दे