Perl Cd Bookshelf [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Perl Cd Bookshelf [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید

13.8. Invoking Methods Indirectly


13.8.1. Problem


You want to invoke a method by a
name that isn''t known until runtime.

13.8.2. Solution


Store the method name as a string in a scalar variable and use it
where you would use the real method name to the right of the arrow
operator:

$methname = "flicker";
$obj->$methname(10); # invokes $ob->flicker(10);
# invoke three methods on the object, by name
foreach $m ( qw(start run stop) ) {
$obj->$m( );
}

13.8.3. Discussion


Sometimes you need to invoke a method whose name you''ve stored
somewhere. You can''t take the address of a method, but you can store
its name. If you have a scalar variable $meth
containing the method name, invoke the method on an object
$crystal with $crystal->$meth(
)
.

@methods = qw(name rank serno);
%his_info = map { $_ => $ob->$_( ) } @methods;
# same as this:
%his_info = (
''name'' => $ob->name( ),
''rank'' => $ob->rank( ),
''serno'' => $ob->serno( ),
);

If you''re desperate to devise a way to get a method''s address, you
should try to rethink your algorithm. For example, instead of
incorrectly taking \$ob->method( ), which
simply applies the backslash to that method''s return value or values,
do this:

my $fnref = sub { $ob->method(@_) };

Now when it''s time to invoke that indirectly, you would use:

$fnref->(10, "fred");

and have the closure in turn correctly use the original value of
$ob (provided $ob was a lexical
variable) that was around when it was created to call:

$ob->method(10, "fred");

This works even if $ob has gone out of scope. This
solution is much cleaner.

When using indirect method invocation, it is permitted to store a
subroutine reference in the scalar variable instead of a string
representing the method name. No verification that the function
represents a valid method.


The code
reference returned by the UNIVERSAL can method
should probably not be used for indirect method invocation on objects
other than the one on which it was called, or at least those of the
same class. That''s because you have no reason to believe that this
will be a valid method when applied to an object of an arbitrary
class.

For example, this is highly dubious code:

$coderef = $some_object->can("wither");
$other_object->$coderef( ); # wither( ) it even if we shouldn''t

That is reasonable only when the two objects are of the same, or
compatible, classes. If they were not, and the second did not have a
wither method, no exception would be raised,
unlike here:

$some_object->wither( );
$other_object->wither( );

Another interesting possibility is to use the strategy outlined in
Recipe 12.5 to implement nominally private
methods.

my $secret_meth = sub { ... }
sub reg_meth {
my $self = shift;
# ... do whatever you want, then
$self->$secret_meth(@_);
#
}

Because the lexical variable $secret_meth is
scoped to the class module''s file, code from outside the class cannot
access it, and therefore cannot invoke the closure. However, code
that is in the module file can see that scalar, so it can use the
code reference with $secret_meth to make an
indirect method invocation.

When you use a code reference to invoke a method indirectly, Perl
doesn''t consult a package or its @ISA at all; it
just makes the function call and passes in the invocant in the
initial slot. That means these two lines are the same:

$self->$secret_meth(@_);        # indirect method invocation
$secret_meth->($self, @_) # indirect function call

So if you hadn''t shifted the invocant off, but had left it in
@_, then you could just make the equivalent
dereferenced function call yourself:

sub reg_meth {
# ... do whatever you want, then
$secret_meth->(@_);
}

13.8.4. See Also


perlobj(1); Recipe 11.8

/ 875