How to check if a subroutine was called with an object invocation method or not
Asked Answered
T

2

6

You can invoke a subroutine as a method using the two syntaxes in the example below.

But you can also invoke it not as an object.

#====================================================
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");
#====================================================

It there a way, from inside the subroutine, to know "in general", what kind of invocation a sub has received?.

Tarlatan answered 10/10, 2016 at 10:56 Comment(1)
Why do you need to know? This sounds like an xy-problem.Disembogue
P
2

You can use called_as_method from 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";
}

Output:

object: Opa Opa -- uno
object: Opa Opa -- uno
class: Opa uno -- segundo
class: Opa Opa -- uno
Palaeozoology answered 10/10, 2016 at 11:17 Comment(0)
E
0

You can also do this with the ref() function instead of using external modules:

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;

Output:

method call
class call
Eversole answered 10/10, 2016 at 14:22 Comment(2)
Subroutines can take references as arguments, so as is this isn't reliable for detecting a method invocation. But ref() provides more: use it to test whether ref($_[0]) provides the class/package name: if (ref($_[0]) eq PACKAGE) { ... }Ashely
[ Bitten by Markdown: That's two underscores concatenated with 'PACKAGE' concatenated with two more underscores. ]Ashely

© 2022 - 2024 — McMap. All rights reserved.