पर्ल विधि कॉल बस नियमित सबरूटीन्स, जो पहले मूल्य के रूप में invocant प्राप्त कर रहे हैं।
use strict;
use warnings;
use 5.10.1;
{
package MyPackage;
sub new{ bless {}, shift } # overly simplistic constructor (DO NOT REUSE)
sub echo{ say @_ }
}
my $package_name = 'MyPackage';
$package_name->echo;
my $object = $package_name->new();
$object->echo; # effectively the same as MyPackage::echo($object)
MyPackage
MyPackage=HASH(0x1e2a070)
आप एक invocant के बिना एक सबरूटीन कॉल करना चाहते हैं, तो आप इसे दूसरे तरीके से कॉल करने के लिए की आवश्यकता होगी।
{
no strict 'refs';
${$package_name.'::'}{echo}->('Hello World');
&{$package_name.'::echo'}('Hello World');
}
# only works for packages without :: in the name
$::{$package_name.'::'}{echo}->('Hello World');
$package_name->can('echo')->('Hello World');
can
विधि सबरूटीन कि अगर यह invocant पर बुलाया गया था कहा जा सकता है के लिए एक संदर्भ देता है। कोडेफ को अलग से इस्तेमाल किया जा सकता है।
यह वास्तव में वह व्यवहार हो सकता है जिसे आप ढूंढ रहे हैं।
एक अन्य दृष्टिकोण symbolic reference नामक किसी चीज़ का उपयोग करना है।
{
no strict 'refs';
&{ $package_name.'::echo' }('Hello World');
}
प्रतीकात्मक संदर्भों का उपयोग आमतौर पर अनुशंसित नहीं किया जाता है। समस्या का एक हिस्सा यह है कि गलती से एक प्रतीकात्मक संदर्भ का उपयोग करना संभव है जहां आप एक का उपयोग करने का इरादा नहीं रखते थे। यही कारण है कि आप use strict 'refs';
प्रभाव में नहीं हो सकते हैं।
यह करने का सबसे आसान तरीका हो सकता है कि आप क्या करना चाहते हैं।
यदि आप प्रतीकात्मक संदर्भ का उपयोग नहीं करना चाहते हैं तो आप Stash का उपयोग कर सकते हैं।
$MyPackage::{echo}->('Hello World');
$::{'MyPackage::'}{echo}->('Hello World');
$main::{'MyPackage::'}{echo}->('Hello World');
$main::{'main::'}{'MyPackage::'}{echo}->('Hello World');
$main::{'main::'}{'main::'}{'main::'}{'MyPackage::'}{echo}->('Hello World');
इस के साथ समस्या सिर्फ आप पर $package_name
विभाजित करने के लिए ::
*Some::Long::Package::Name::echo = \&MyPackage::echo;
$::{'Some::'}{'Long::'}{'Package::'}{'Name::'}{echo}('Hello World');
sub get_package_stash{
my $package = shift.'::';
my @package = split /(?<=::)/, $package;
my $stash = \%:: ;
$stash = $stash->{$_} for @package;
return $stash;
}
get_package_stash('Some::Long::Package::Name')->{echo}('Hello World');
यह हालांकि कि एक समस्या का बड़ा नहीं है के लिए होता है। CPAN पर त्वरित रूप से देखने के बाद आपको Package::Stash मिल जाएगा।
use Package::Stash;
my $stash = Package::Stash->new($package_name);
my $coderef = $stash->get_symbol('&echo');
$coderef->('Hello World');
यह ऐसा है से आयात किया गया था, सबरूटीन/विधि के उपनाम के बनाने के लिए भी संभव है (Package::Stash की Pure Perl संस्करण प्रतीकात्मक संदर्भ, नहीं छिपाने की जगह का उपयोग करता है) एक मॉड्यूल जो Exporter का उपयोग कर रहा था:
*echo = \&{$package_name.'::echo'};
echo('Hello World');
मैं आर ecommend हालांकि उर्फ के दायरे को सीमित:
{
local *echo = \&{$package_name.'::echo'};
echo('Hello World');
}
यह एक अपवाद है, जहां आप strict 'refs'
को सक्षम करने पर एक प्रतीकात्मक संदर्भ का उपयोग कर सकते है।
स्रोत
2012-06-05 02:40:14
यदि आप एक आक्रमणकर्ता को पास नहीं करना चाहते हैं, तो आप जो चाहते हैं वह * विधि * को कॉल नहीं करना है। – hobbs
@ हॉब्स: धन्यवाद। मैंने प्रश्न को और सही शब्दावली का उपयोग करने के लिए अद्यतन किया है। "नो सख्त 'रेफरी के लिए – Sam