2010-08-04 10 views
12

मेरा लक्ष्य इस तरह $obj उपयोग करने के लिए सक्षम होने के लिए है:पर्ल: फ्लाई पर ऑब्जेक्ट्स कैसे बनाएं?

print $obj->hello() . $obj->{foo}; 

और मैं एक वस्तु इनलाइन बनाने के लिए, हो सकता है कुछ इस तरह का उपयोग कर चाहते हैं:

my $obj = (
    foo => 1, 
    hello => sub { return 'world' } 
); 

लेकिन जब मैं कोशिश किसी ऑब्जेक्ट के रूप में $obj का उपयोग करने के लिए, मुझे यह कहते हुए एक त्रुटि मिलती है कि $ obj को को आशीर्वाद नहीं दिया गया है। क्या कुछ बेस क्लास है (जैसे PHP में stdClass) मैं हैश को आशीर्वाद देने के लिए उपयोग कर सकता हूं ताकि मैं इसे किसी ऑब्जेक्ट के रूप में उपयोग कर सकूं?


उन है कि जावास्क्रिप्ट जानते हैं, मैं निम्नलिखित करने के लिए कोशिश कर रहा हूँ, लेकिन पर्ल में:

# JS CODE BELOW 
var obj = { foo: 1, hello: function() { return 'world' } }; 
echo obj.hello() + obj.foo; 
+0

पर्ल तरीकों हैश पर खेतों नहीं हैं - यह जावा नहीं है। – Ether

+0

जावास्क्रिप्ट या तो जावा नहीं है। – cjm

उत्तर

14

पर्ल को ऐसा करने में थोड़ी मदद की आवश्यकता होगी। क्योंकि यह हैश में संग्रहीत कोड संदर्भों को "विधियों" के रूप में नहीं मानता है। एक पैकेज प्रतीक तालिका में प्रविष्टियों के रूप में तरीके लागू किए जाते हैं।पर्ल अधिक जावास्क्रिप्ट की तुलना में कक्षा-उन्मुख है, जो गर्व से यह घोषणा करता है कि यह ऑब्जेक्ट-ओरिएंटेड (व्यक्तिगत ऑब्जेक्ट्स पर) है।

उस कार्यक्षमता को करने के लिए, आपको एक कक्षा बनाना होगा जो इस तरह से संदर्भित मैप किए जाएंगे। प्रतीक तालिका में चारों ओर विधियों को पाने का तरीका AUTOLOAD विधि है। यदि किसी पैकेज में AUTOLOAD सबराउटिन होता है, जब किसी धन्य ऑब्जेक्ट पर कॉल किया जाता है जिसे पर्ल विरासत श्रृंखला में नहीं मिल पाती है, तो यह AUTOLOAD पर कॉल करेगी और पैकेज-स्कोप्ड (our) चर $AUTOLOAD सेट करें पूर्ण नाम का नाम होगा समारोह।

हमें पूरी तरह से योग्य उप नाम के अंतिम नोड (अंतिम '::' के बाद) नामक विधि का नाम मिलता है। हम देखते हैं कि उस स्थान पर एक कोडफ्रफ़ है या नहीं, और यदि वहां है, तो हम इसे वापस कर सकते हैं।

package AutoObject; 

use strict; 
use warnings; 
use Carp; 
use Params::Util qw<_CODE>; 
our $AUTOLOAD; 

sub AUTOLOAD { 
    my $method_name = substr($AUTOLOAD, index($AUTOLOAD, '::') + 2); 
    my ($self) = @_; 
    my $meth  = _CODE($self->{$method_name}); 
    unless ($meth) { 
     Carp::croak("object does not support method='$method_name'!"); 
    } 
    goto &$meth; 
} 


1; 

तो फिर तुम उस वर्ग में वस्तु आशीर्वाद होगा:

package main; 

my $obj 
    = bless { foo => 1 
     , hello => sub { return 'world' } 
     }, 'AutoObject'; 

print $obj->hello(); 

आम तौर पर, एक AUTOLOAD उप में मैं "सीमेंट" व्यवहार। यही है, अगली बार AUTOLOAD से बचने के लिए, मैं पैकेज प्रतीक तालिका में प्रविष्टियां बनाता हूं। लेकिन यह आमतौर पर एक उचित परिभाषित वर्ग व्यवहार के लिए है।

मैंने QuickClass भी डिज़ाइन किया है जो प्रत्येक ऑब्जेक्ट के लिए एक पैकेज बनाता है, लेकिन इसमें बहुत सी प्रतीकात्मक तालिका है जो अब Class::MOP के साथ बेहतर है।


एरिक स्ट्रॉम द्वारा दिए गए सुझाव को देखते हुए, आप निम्न कोड ऑटोऑब्जेक्ट पैकेज में जोड़ सकते हैं। import उप किसी को कभी भी use -d AutoObject (पैरामीटर 'object' के साथ) कहा जाएगा।

# Definition: 
sub object ($) { return bless $_[0], __PACKAGE__; }; 

sub import { # gets called when Perl reads 'use AutoObject;' 
    shift; # my name 
    return unless $_[0] eq 'object'; # object is it's only export 
    use Symbol; 
    *{ Symbol::qualify_to_reference('object', scalar caller()) } 
     = \&object 
     ; 
} 

और तब, जब आप एक "शाब्दिक वस्तु" बनाना चाहता था, तो आप सिर्फ कर सकता है:

use AutoObject qw<object>; 

और अभिव्यक्ति होगा:

object { foo => 1, hello => sub { return 'world' } }; 

तुम भी कर सकता है :

object { name => 'World' 
     , hello => sub { return "Hello, $_[0]->{name}"; } 
     }->hello() 
     ; 

और आपके पास "ऑब्जेक्ट" है शाब्दिक "अभिव्यक्ति। शायद मॉड्यूल बेहतर होगा Object::Literal

+0

यह वास्तव में एक आसान चाल है। अगर मैंने कभी पर्ल में ओओपी का इस्तेमाल किया तो मैं इसे अच्छे इस्तेमाल के लिए रख सकता हूं। –

+0

आप कॉलिंग कोड को उप-उप-आशीर्वाद में आशीर्वाद छुपाकर थोड़ा क्लीनर बना सकते हैं {आशीर्वाद $ _ [0] => 'ऑटोऑब्जेक्ट'} 'और फिर' मेरा $ obj = object {...}; ' –

+0

@ एरिक स्ट्रॉम: यह अच्छी समझ में आता है। लेकिन यहां मेरी सोच है: जावास्क्रिप्ट मुहावरे मूल रूप से एक "ऑब्जेक्ट शाब्दिक" है। पर्ल में, "ऑब्जेक्ट शाब्दिक" (अक्सर) 'आशीर्वाद {...},' MyClass 'है। * बेशक *, चूंकि 'आशीर्वाद' सिर्फ एक मजेदार है, इसलिए कोई कारण नहीं है कि 'ऑब्जेक्ट {...}' बेहतर शाब्दिक नहीं है। मैं अपना कोड बदल दूंगा। – Axeman

2

$obj एक अदिश होगा, इसलिए करने के लिए यह रूप में एक अदिश हो गया है जो कुछ भी आप आवंटित कुंआ। आप या तो कह सकते हैं

my %obj = (foo => 1, hello => sub { return 'world' }); 

या

my $obj = { foo => 1, hello => sub { return 'world' }}; 

बाद, घुंघराले ब्रेसिज़ के साथ, एक हैश संदर्भ बनाता है (जो एक अदिश है, तो यह $obj में जा सकते हैं)। हैश संदर्भ के अंदर सामान प्राप्त करने के लिए, हालांकि, आपको तीर ऑपरेटर का उपयोग करना होगा। कुछ $obj->{foo} या &{$obj->{hello}} जैसे कुछ।

जब तक आपको हैश की सूचियां या कुछ ऐसा करने की आवश्यकता न हो, तो आमतौर पर पहली विधि का उपयोग करना बेहतर होता है।

किसी भी तरह से, आप $obj->hello() कहने में सक्षम नहीं होंगे। पर्ल ओओपी के अपने स्वाद के लिए उस वाक्यविन्यास का उपयोग करता है, जिसमें एक अलग पैकेज में hello फ़ंक्शन होगा जो आपका संदर्भ bless एड में रहा है। जैसा:

package example; 
sub new {} { my $result = {}; return bless $result, 'example' } 
sub hello { return 'world' } 

package main; 
my $obj = example->new(); 

आप देख सकते हैं, तरीकों आप कॉल कर सकते हैं पहले ही निर्धारित कर, और इसे और अधिक जोड़ने के लिए तुच्छ नहीं है। ऐसे जादू तरीके हैं जिनका उपयोग आप ऐसी चीज करने के लिए कर सकते हैं, लेकिन वास्तव में, यह इसके लायक नहीं है। &{$obj{hello}} (या &{$obj->{hello}} संदर्भ के लिए) पर्ल काम को जावास्क्रिप्ट की तरह काम करने की कोशिश करने से कम प्रयास है।

+0

खैर, यह मुझे शेष दिन के लिए सामग्री पढ़ता है ... – Tom

0

पर्ल में तरीके वस्तु के गुण नहीं हैं जैसे कि वे पाइथन में हैं। ऑब्जेक्ट से जुड़े पैकेज में विधि नियमित नियमित कार्य फ़ंक्शन हैं। नियमित संदर्भ स्वयं संदर्भ के लिए एक अतिरिक्त तर्क ले रहे हैं।

आप विधियों के रूप में गतिशील रूप से बनाए गए कार्यों को नहीं बना सकते हैं।()

1. An object is simply a reference that happens to know which class it 
     belongs to. 

    2. A class is simply a package that happens to provide methods to deal 
     with object references. 

    3. A method is simply a subroutine that expects an object reference 
     (or a package name, for class methods) as the first argument. 

ओह, और आशीर्वाद है कि कैसे आप संदर्भ और पैकेज के बीच कनेक्शन स्थापित है:

यहाँ perldoc perlobj से एक उद्धरण है।

+0

यह सुनिश्चित करके आपके मन में क्या है कि * "आप गतिशील रूप से कार्यों को विधियों के रूप में नहीं बना सकते हैं।" * कोई गतिशील रूप से कार्यों को उत्पन्न कर सकता है और उन्हें सम्मिलित कर सकता है एक पैकेज। कई सीपीएएन मॉड्यूल ऐसा करते हैं। काफी सरल उदाहरण के रूप में, Getopt :: Long :: वर्णनात्मक देखें। उपयोगकर्ता द्वारा अनुरोध किए गए प्रत्येक विकल्प पार्सर के लिए, यह एक नया वर्ग नाम उत्पन्न करता है। उस पैकेज में यह उपयोगकर्ता द्वारा परिभाषित प्रत्येक कमांड लाइन विकल्प के लिए एक गेटर स्थापित करता है। – FMc

+0

मेरा मतलब है कि आप एक तरीका नहीं जोड़ सकते जिस तरह से वह इसे करना चाहता है। गतिशील फ़ंक्शन सम्मिलन इस से अधिक जटिल है ("कोई सख्त रेफरी; * {" $ पैकेज \ :: फ़ंक्शन "} = उप {...};", कोई भी? गह!) और हल्के ढंग से नहीं किया जाना चाहिए। – Arkadiy

1

जो भी फ़ंक्शन आप ऑब्जेक्ट बना रहे हैं, आपको विधि कॉलिंग सक्षम करने के लिए अपने ऑब्जेक्ट पर bless पर कॉल करने की आवश्यकता है।

उदाहरण के लिए:

package MyClass; 

sub new 
{ 
    my $obj = { 
    foo => 1 
    }; 

    return bless($obj, "MyClass"); 
} 

sub hello 
{ 
    my $self = shift; 
    # Do stuff, including shifting off other arguments if needed 
} 

package main; 
my $obj = MyClass::new(); 

print "Foo: " . $obj->{foo} . "\n"; 
$obj->hello(); 

संपादित करें: यदि आप अपने वस्तुओं के लिए गतिशील सुविधा प्रदान करने के सबरूटीन संदर्भ का उपयोग करने में सक्षम होना चाहते हैं ...

my $obj = MyClass::new(); # or whatever 
$obj->{hello}->(@myArguments); 

एक छोटी सी बोझिल है, लेकिन यह:

सबसे पहले, आप तो जैसे (इस हैश निर्माता उदाहरण के अंदर) के अपने कोड संदर्भ बना सकते हैं:

my $obj = { 
    foo => 1, 
    hello => sub { print "Hello\n"; }, 
} 

फिर आप इस तरह यह आह्वान कर सकते हैं काम करता है। (तुम भी दूसरा तीर की जरूरत हो सकती है, लेकिन मुझे यकीन है कि नहीं कर रहा हूँ।)

2

यह पर्ल में अलग ढंग से एक छोटा सा वर्तनी:

my $obj = { foo => 1, hello => sub { return "world" } }; 
print $obj->{hello}() . $obj->{foo}; 

लेकिन कोड अजीब है। संदर्भ के बारे में आपने जो चेतावनी देखी है, वह आपको आशीर्वाद नहीं दे रहा है कि आपकी वस्तुएं the way Perl expects में लागू नहीं की गई हैं। bless ऑपरेटर पैकेज के साथ एक ऑब्जेक्ट चिह्नित करता है जिसमें इसकी विधियों की खोज शुरू होती है।

हमें बताएं कि आप अपनी समस्या डोमेन के संदर्भ में क्या करना चाहते हैं, और हम पर्ल में एक और प्राकृतिक दृष्टिकोण के लिए सुझाव दे सकते हैं।

4

एक अधिक पर्लिश दृष्टिकोण आपके ऑब्जेक्ट की वांछित विधियों के लिए अलग नामस्थान बनाने और bless ऑब्जेक्ट को आपके ऑब्जेक्ट के लिए उपलब्ध कराने के लिए ऑब्जेक्ट बनाने के लिए है। ऐसा करने के लिए कोड अभी भी काफी सफल हो सकता है।

my $obj = bless { foo => 1 }, "bar"; 
sub bar::hello { return 'world' }; 

gbacon, से पता चलता है अगर आप $obj->{hello}->() बजाय $obj->hello() लिखने के लिए तैयार हैं, तुम्हें आशीर्वाद दे आपरेशन छोड़ सकते हैं।

my $obj = { foo => 1, hello => sub { return 'world' } }; 
0

मैं क्लास :: स्ट्रक्चर का उपयोग करने की सलाह देता हूं जैसा कि पर्लोट मैन पेज में बताया गया है।

वस्तुओं जिसका क्षेत्रों के लिए एक विशिष्ट के हैं होने के रूप में एक वर्ग की घोषणा "" आप एक तरह से करने के लिए प्रदान करते हैं क्या यह करता है ": प्रलेखन टीका की

इसके बजाय, मुझे यह बोली के रूप में यह बताया गया है यह अच्छी तरह से कैसे काम करता है टाइप करें। यह फ़ंक्शन जो इसे करता है, आश्चर्यजनक रूप से पर्याप्त नहीं है, संरचना()। क्योंकि संरचना या रिकॉर्ड पर्ल में आधार प्रकार नहीं हैं, हर बार जब आप रिकॉर्ड-जैसी डेटा ऑब्जेक्ट प्रदान करने के लिए कक्षा बनाना चाहते हैं, तो आपको स्वयं को उस रिकॉर्ड के फ़ील्ड के लिए एक नई() विधि, साथ ही अलग डेटा-एक्सेस विधियों को परिभाषित करें। आप इस प्रक्रिया के साथ जल्दी से ऊब जाएंगे। कक्षा :: संरचना :: संरचना() फ़ंक्शन इस टेडियम को कम करता है। "

फिर भी दस्तावेज़ से उद्धृत यह कैसे लागू करने पर एक उदाहरण तरीका है:

use Class::Struct qw(struct); 
use Jobbie; # user-defined; see below 
struct 'Fred' => { 
    one  => '$', 
    many  => '@', 
    profession => 'Jobbie', # does not call Jobbie->new() 
}; 
$ob = Fred->new(profession => Jobbie->new()); 
$ob->one("hmmmm"); 
$ob->many(0, "here"); 
$ob->many(1, "you"); 
$ob->many(2, "go"); 
print "Just set: ", $ob->many(2), "\n"; 
$ob->profession->salary(10_000); 
संबंधित मुद्दे