Jeśli $name='name'
działadziała, ale nie $object_ref->('name')
?Jak wywołać nazwę funkcji zdefiniowaną w literalnym łańcuchu w perlu?
Odpowiedz
$obj->$name # Method call with no args
$obj->name # Method call with no args
$obj->$name() # Method call with no args
$obj->name() # Method call with no args
$sub->('name') # Sub call (via ref) with one arg.
sub('name') # Sub call with one arg.
Składnia dla wywołań metod to $object->method
lub $object->$method
. Składnia, którą podałeś, może być jednak użyta dla $sub_ref->(@param)
.
W języku Perl symbol ->
ma dwa znaczenia. Jeśli po nim jest wpisane $obj->name
lub skalarne $obj->$name
, wówczas ->
oznacza wywołanie metody.
Jeśli zamiast ->
następuje nawias klamrowy otwarcia, to jest to dereference, zgodnie z poniższą tabelą:
$obj->(...) # dereference as code, which calls the subroutine
$obj->[...] # dereference as array, which accesses an element
$obj->{...} # dereference as hash, which accesses an element
Kiedy ->
jest dereferencing wartość, Perl będzie sprawdzić, czy wartość jest albo typ wskazany przez nawias klamrowy, albo może być wymuszony na ten typ przez przeciążenie. Tak więc ->(
w twoim przykładzie oznacza, że perl spróbuje przekonwertować $object_ref
na odwołanie do kodu, i prawdopodobnie zakończy się niepowodzeniem, zgłaszając błąd.
Jeśli ->
jest wywołanie metody, a następnie perl robi coś takiego:
if (reftype $name eq 'CODE') { # if $name is code, ignore $object_ref's type
$name->($object_ref) # call the coderef in $name, with $object_ref
} # followed by any other arguments
elsif (my $code = $object_ref->can($name)) { # otherwise, try to look up the
# coderef for the method named $name in $object_ref's namespace and then
$code->($object_ref) # call it with the object and any other arguments
}
else {die "no method $name on $object_ref"}
tylko do rzeczy jaśniej:
sub foo {"foo(@_)"}
my $foo = \&foo;
say foo 'bar'; # 'foo(bar)'
say $foo->('bar'); # 'foo(bar)'
say 'bar'->$foo; # 'foo(bar)'
i
sub Foo::bar {"Foo::bar(@_)"}
my $obj = bless [] => 'Foo';
my $method = 'bar';
say $obj->bar(1); # Foo::bar($obj, 1)
say $obj->$method(1); # Foo::bar($obj, 1)