Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Is reference blessed?

by gildir (Pilgrim)
on Nov 23, 2001 at 14:22 UTC ( [id://127079]=perlquestion: print w/replies, xml ) Need Help??

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

Fellow monks,

I want to check if some reference (say $r) is blessed or not.
Is there some easy way to do it, except for cumbersome, ugly and non-general hack like this:

if (ref $r ne 'HASH' && ref $r ne 'ARRAY' && ref $r ne 'CODE' && ref $ +r ne 'SCALAR' && ref $r ne 'GLOB')

And another question: How do I get the real type of reference, even if it is blessed. I mean, that is I have an object $o of class Foo::Bar, ref $o allways returns Foo::Bar. How do I chcek if $o is blessed reference to HASH or to ARRAY or whatever?

I have been peeking into some modules around (Data::Dumper I think) and found only this ugly code

my ($class,$type,$addr) = (overload::StrVal($r) =~ /^(?:(.*)\=)?([^=]* +)\(([^\(]*)\)$/);
Is this the only way?
I have considered perl an elegant language (when used correctly) a I do not like this.

Replies are listed 'Best First'.
Re: Is reference blessed?
by jeroenes (Priest) on Nov 23, 2001 at 14:58 UTC
    Yes you can find out whether an object is blessed more elegantly (tye and merlyn told me): if UNIVERSAL::isa($ref,'can'){

    And as for your type finding, this is from perldoc perlobj:

    isa(CLASS)
    `isa' returns true if its object is blessed into a subclass of `CLASS' `isa' is also exportable and can be called as a sub with two arguments. This allows the ability to check what a reference points to. Example:
    if(UNIVERSAL::isa($ref, 'ARRAY')) {...

    HTH,

    Jeroen
    "We are not alone"(FZ)

    Update: Yeah I screwed up remembering tye's solution. I looked it up (mea culpa):
    $ref->can('isa')
    Is the beast you are looking for.

    Update2: D'oh. I took it for granted that you wanted a ref-check anyway, like if( ref $r ){ if ($r->can('isa')){.... Your UNIVERSAL::can($r, 'isa') sounds really neat. I'm curiously awaiting tye's/ merlyn's response(s).

      I think it should be
      if (UNIVERSAL::can($ref,'isa')) { ...
      But I see the point now.
      As UNIVERSAL is the parent of every object (blessed reference) and it implements method 'isa', every beast that know how to call isa method must be an object.

      Update: No, $r->can('isa') won't work (as I mentioned in the other reply) because if $r is not blessed, it will die on 'unblessed reference' error. UNIVERSAL::can($r,'isa') is real solution.

      Update2: Even if I do refcheck, situation is the same. I just cannot call any method on non-blessed reference, not even the can() method. Consider $r={}; you cannot do $r->can() because $r is not blessed. And that is what I want to know, if $r is blessed or not. I know that it is a reference. Catching a die exception with eval is TIMTOWDI, but it does not look good to me :-)

        The problem with just UNIVERSAL::can($ref,'isa') is that it can return a true value when $ref isn't even a reference. So you really have to make multiple tests:

        if( ! ref($r) ) { # no reference at all } elsif( ! UNIVERSAL::can($r,'can') ) { # unblessed ref } else { # blessed ref }
        or just:
        if( ref($r) && UNIVERSAL::can($r,'can') ) { # blessed ref }
        or
        if( ref($r) && eval { $r->can('can') } ) { # blessed ref }
        and I can't make a convincing case for one style over the other at the moment.

        And, yes, it would be nice if there were less overloaded versions of these things so that blessed returned the package that a reference was blessed into and ref just always returned the type of thing. That was a certainly a design mistake IMO.

                - tye (but my friends call me "Tye")
Re: Is reference blessed?
by davorg (Chancellor) on Nov 23, 2001 at 15:02 UTC

    Sounds like you need the blessed function from gbarr's Scalar::Util module.

    This module is included with the standard distribution from 5.7.2.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you don't talk about Perl club."

Re: Is reference blessed?
by clintp (Curate) on Nov 23, 2001 at 22:02 UTC
    Here's one way to tell, extracted from an example in the Perl Developer's Dictionary:
    # To be honest: if you're not sure what's in $t # at all, then things begin to get silly. if ($type = ref $t) { eval { $t->isa("UNIVERSAL"); }; if ( $@=~/unblessed/ ) { print "It's a $type, not blessed.\n" } else { print "It's blessed into class $type"; } } else { print "Not a reference at all\n"; }
Re: Is reference blessed?
by pike (Monk) on Nov 23, 2001 at 15:09 UTC
    Try:

    $r->isa('UNIVERSAL');
    Background: all classes inherit from UNIVERSAL, (e.g. methods like 'isa'), therefore the above returns true for all blessed references

    pike

      Won't work.

      If $r is not blessed, you get an 'Can't call method "isa" on unblessed reference' error.
      But, as I see it now

      UNIVERSAL::isa($r,"UNIVERSAL")
      will work
Re: Is reference blessed?
by brycen (Monk) on Mar 26, 2010 at 02:23 UTC
    Answering the 2nd half of the question, nine years late:
    # We want the true type of blessed objects like XML::DOM::Document my $true_type; if(ref($value)) { $true_type = scalar($value); $true_type =~ s/.*=(\w*).*/$1/; } print ref($value)," is really an $true_type\n";
    XML::DOM::Document is really an ARRAY
    That's ugly. It takes the scalar value of the reference, which just happens to show both the blessed type and the native type. But it works.

      No, that doesn't work.

      { package Foo; use overload '""' => sub { 'Bar' }; sub new { bless({}, shift) } } { my $value = Foo->new; # We want the true type of blessed objects like XML::DOM::Document my $true_type; if(ref($value)) { $true_type = scalar($value); $true_type =~ s/.*=(\w*).*/$1/; } print ref($value)," is really an $true_type\n"; }
      Foo is really an Bar

      But it's really a hash.

      Scalar::Util's blessed, reftype and refaddr provide the desired $class, $type and $addr respectively.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-03-29 06:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found