Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Calling can method

by gildir (Pilgrim)
on May 30, 2001 at 12:48 UTC ( [id://84194]=perlquestion: print w/replies, xml ) Need Help??

gildir has asked for the wisdom of the Perl Monks concerning the following question:

I've noticed several people (for example here) calling can method in this way: UNIVERSAL::can('Test', 'foo'). Doesn't this break inheritance? Imagine class Test be a subclass of SuperTest which implements method foo(). Will this code return true or false?

I tried a test, and UNIVERSAL::can is aware of inheritance. And I'm little bit confused now. UNIVERSAL::can('Test', 'foo') looks like a bad practice when compared to Test->can('foo'). Is it just a hack in UNIVERSAL::can that make it work in the 'bad' way or is it a planned feature? Is UNIVERSAL::can('Test', 'foo') used for performance reasons (to avoid traversing ISA hierarchy twice)?

Replies are listed 'Best First'.
Re: Calling can method
by jeroenes (Priest) on May 30, 2001 at 13:03 UTC
    You just have no choice, if you don't have an instance of the class. So if there is no object created, the UNIVERSAL::can is the only way to test if that class provides that method.

    Cheers,

    Jeroen
    "We are not alone"(FZ)

    Update: Ahum... indeed. The perl OO is really confusing. But, now I remember again, UNIVERSAL::can('Test','foo') is actually the same as Test->can('foo'). Because in the last case, the word Test gets unshifted into @_, and the method 'can' is found in UNIVERSAL. So internally, actually UNIVERSAL::can is called, with the args ('Test', @_), which comes down to the same.

    So this is actually a feature, not a bug {grin}

    To clarify a bit more (mehopes):

    package Test; package main; print "it works\n" if Test->UNIVERSAL::can('can'); print "it works\n" if Test->SUPER::can('can');
    You see? The Package::can only gives the route to the method (if not given, perl finds it from ISA). The -> only tells which thing to unshift in @_.

    Of course, the sub need a way to filter out whether they are called with a Package or an object. So the trick doesn't work with all methods.

    It's explained also in the 'Inheritance' section of perltoot.

      No no no no,

      I can call any static method by ClassName->method. Including 'can' method. I can safely call Test->can('foo'). I have tried that. It works and I use it frequently.

        You can't safely call $x->can('foo') though, although you can always call UNIVERSAL::can($x, 'foo'), which is where the idiom comes from. True, it's overkill for the class case, but for the instance case, it's mandatory.

        -- Randal L. Schwartz, Perl hacker

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://84194]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-19 01:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found