2016-10-10 34 views
5

Możesz wywołać podprogram jako metodę, używając dwóch składni w poniższym przykładzie.Jak sprawdzić, czy podprogram został wywołany z metodą wywołania obiektu, czy nie

Ale można go również wywołać nie jako obiekt.

#==================================================== 
package Opa; 
sub opa{ 
    $first= shift; 
    $second= shift; 
    print "Opa $first -- $second\n"; 
} 

package main; 
# as object: 
Opa->opa("uno"); 
opa Opa ("uno"); 
# not as object 
Opa::opa("uno","segundo"); 
Opa::opa("Opa","uno"); 
#==================================================== 

Jest jakiś sposób, od wewnątrz podprogramu, aby wiedzieć „w ogóle”, jakie wywołania sub otrzymał ?.

+6

dlaczego trzeba wiedzieć? To brzmi jak problem XY. – simbabque

Odpowiedz

2

Możesz użyć called_as_method z Devel::Caller.

use Devel::Caller qw(called_as_method); 
sub opa{ 
    print called_as_method(0) ? 'object: ' : 'class: '; 
    $first= shift; 
    $second= shift; 
    print "Opa $first -- $second\n"; 
} 

wyjściowa:

object: Opa Opa -- uno 
object: Opa Opa -- uno 
class: Opa uno -- segundo 
class: Opa Opa -- uno 
+0

Dziękuję bardzo! –

0

Można to zrobić także z funkcją ref() zamiast korzystania z zewnętrznych modułów:

use warnings; 
use strict; 

package Test; 

sub new { 
    return bless {}, shift; 
} 
sub blah { 
    if (ref $_[0]){ 
     print "method call\n"; 
    } 
    else { 
     print "class call\n"; 
    } 
} 

package main; 

my $obj = Test->new; 

$obj->blah; 
Test::blah; 

wyjściowa:

method call 
class call 
+1

Podprogramy mogą przyjmować referencje jako argumenty, tak jak to nie jest niezawodne w wykrywaniu wywołania metody. Ale ref() zapewnia więcej: użyj go, aby sprawdzić, czy ref ($ _ [0]) dostarcza nazwę klasy/pakietu: if (ref ($ _ [0]) eq __PACKAGE__) {...} –

+0

[Ugryziony przez Markdown : To są dwa podkreślenia połączone ze "PAKIETEM" połączone dwoma dodatkowymi podkreśleniami. ] –