Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Is there a way to find out what kind of ref an object is?

by johnnywang (Priest)
on Dec 06, 2005 at 23:33 UTC ( [id://514670]=perlquestion: print w/replies, xml ) Need Help??

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

Some recent nodes about inside-out objects got me thinking about how to find out about the implementation of a regular object. In particular, is there any way to find out whether an object is implemented as a hash reference or array reference:
use strict; package A; sub new{ bless {},shift; } package B; sub new{ bless [], shift; } package main; my $a = A->new; my $b = B->new; my $c = {}; my $d = []; print "\$a is of type: ", ref($a), "\n"; print "\$b is of type: ", ref($b), "\n"; print "\$c is of type: ", ref($c), "\n"; print "\$d is of type: ", ref($d), "\n"; __OUTPUT__ $a is of type: A $b is of type: B $c is of type: HASH $d is of type: ARRAY
of course if you do $b->{1} = 2, you will get an error. How do I find out that $a is a hash ref, while $b is a array ref?

Replies are listed 'Best First'.
Re: Is there a way to find out what kind of ref an object is?
by blokhead (Monsignor) on Dec 06, 2005 at 23:47 UTC
    You can use the reftype function from Scalar::Util, which is a core module in recent perls. It's a little more robust, works for blessed and unblessed refs, and doesn't rely on non-overloaded stringification like the solution above.

    blokhead

Re: Is there a way to find out what kind of ref an object is?
by chromatic (Archbishop) on Dec 07, 2005 at 00:47 UTC
    Some recent nodes about inside-out objects got me thinking about how to find out about the implementation of a regular object.

    If you have to ask, you're probably doing something scary and probably dangerous. The purpose of inside-out objects is to prevent you from doing such dangerous things accidentally.

    For curiosity's sake, reftype() is the most accurate approach, though heed ysth's example carefully. The documentation is the best place to learn what you can and cannot and should and should not do with an object.

      well, exactly, it's dangerous. My impression of the purpose of inside-out objects is to prevent users from messing up the contents of hashref in the implementation, which I assume means directly change the content via the object reference, and to do that one needs to know its type (reference of hash, array, scalar , etc.), hence my original question.
Re: Is there a way to find out what kind of ref an object is?
by psychotic (Beadle) on Dec 06, 2005 at 23:40 UTC
    Here is our module, Hello.pm:

    package Hello; use strict; sub new { my $class = shift; my $this = {}; return bless $this, $class; } 1;

    And here we use this script:

    use strict; use Hello; my $a = Hello->new(); print $a;

    When the above is run, it gives:

    Hello=HASH(0x225388)

    ..which is self-documenting. ;) Hope this helps!

Re: Is there a way to find out what kind of ref an object is?
by santonegro (Scribe) on Dec 06, 2005 at 23:47 UTC
    the first thing that comes to mind is:
    eval { keys %$ref } ; print "its a hash" unless $@;
      use overload '%{}'=>sub{{}}; sub new { bless [] } $ref = new(); eval { keys %$ref } ; print "is it a hash?" unless $@;
        That'd be the correct answer most of the time - if an object promises says it "can do" a hash interface, its up to everyone but the most sneaky to go by that.
Re: Is there a way to find out what kind of ref an object is? (isa)
by tye (Sage) on Dec 07, 2005 at 07:26 UTC

    I'd probably use:

    BEGIN { *isa= \&UNIVERSAL::isa; } ... isa( $ref, 'HASH' ) ...

    which isn't perfect, but neither are any of the techniques I've seen that aren't unreasonably complicated, unfortunately.

    - tye        

      neither are any of the techniques I've seen that aren't unreasonably complicated, unfortunately.

      Is:

      use Scalar::Util qw( reftype ); ... print "$ref is a ", reftype( $ref ), "\n";

      unreasonably complicated?

        I guess you are assuming that it is perfect. But it isn't. It prevents you from properly handling overloaded objects that know how to act like a hash ref even though they aren't.

        Of course, it is also overly complicated in many cases. For example, on the version of Perl I have most handy, it simply dies with Can't locate Scalar/Util.pm and overcoming that is rather hugely complicated, as it happens.

        - tye        

        It has the misfortune of working correctly, as opposed to ref or UNIVERSAL::isa().

Re: Is there a way to find out what kind of ref an object is?
by neosamuri (Friar) on Dec 07, 2005 at 05:29 UTC

    It would be helpful to look at perlobj. The function that you are looking for is ref. Here is an example from perlobj, that shows what you are looking for:

    $a = {}; $b = $a; bless $a, BLAH; print "\$b is a ", ref($b), "\n";

      Actually, ref doesn't give the underlying implementation. In the example code you gave, it should give 'BLAH', which doesn't tell you if 'BLAH' is an arrayref, or a hashref:

      for my $i ( [], {} ) { bless $i, 'BLAH'; printf( "%s\t%s\n", ref($i), $i ) }

      I typically use tye's answer, and go with UNIVERSAL::isa. (eg, if I'm dealing with structures passed in from a SOAP call, and I want to make sure the structure is right, even if the class name is wrong, before I start to manipulate it)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-04-23 13:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found