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

Dear monks,

let's say I have a class like so:
package Node; sub new { my $class = shift; my $self = {}; my $self->{parent} = undef; bless $self, $class; return $self; } sub parent { my $self = shift; if ( @_ ) { $self->{parent} = shift; } return $self; }
And I do the following:
use Node; my ( $child, $parent ) = ( new Node, new Node ); $child->parent($parent);
Does the hash value $child->{parent} now hold the blessed hash that was created when I did $parent = new Node;, or a reference to it? I think it's a reference, but I'm not completely sure...

Replies are listed 'Best First'.
Re: objects are references, right?
by polettix (Vicar) on Jul 05, 2005 at 23:46 UTC
    Data::Dumper is your friend for this issues:
    #!/usr/bin/perl use strict; use warnings; package Node; sub new { my $class = shift; my $self = {}; $self->{parent} = undef; bless $self, $class; return $self; } sub parent { my $self = shift; if ( @_ ) { $self->{parent} = shift; } return $self; } package main; use Data::Dumper; my ( $child, $parent ) = ( new Node, new Node ); $child->parent($parent); print Dumper($parent); print Dumper($child); __END__ perl rvosa.pl $VAR1 = bless( { 'parent' => undef }, 'Node' ); $VAR1 = bless( { 'parent' => bless( { 'parent' => undef }, 'Node' ) }, 'Node' );
    As you can see, both child and parent are blessed references (to hashes, in this case), and the same applies to $child->{parent}, which happens to be equal to $parent.

    Note that I also activated strict and warnings, which spotted an error in your constructor:

    sub new { my $class = shift; my $self = {}; my $self->{parent} = undef; # <<< you "my" $self twice! bless $self, $class; return $self; }

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Don't fool yourself.
      Thanks! I've been using a more baroque version of the code I free-typed in here for a while now, and I've been checking with Data::Dumper already, but somehow I'm having difficulty with its coding style sometimes :)

      This clarifies things - it's the way I thought, but sometimes it's nice to have confirmation.
        I tend to use the x debugger command, which in some cases makes it more obvious:
        DB<2> x $child 0 Node=HASH(0x1c58f28) 'parent' => Node=HASH(0x1d9b770) 'parent' => undef DB<3> x $parent 0 Node=HASH(0x1d9b770) 'parent' => undef
        You can see by the hash addresses that $parent and $child{'parent'} point to the same hash. This is not immediately obvious with Data::Dumper.

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Re: objects are references, right?
by dragonchild (Archbishop) on Jul 06, 2005 at 01:06 UTC
    On a completely unrelated note, you will want to eschew the indirect syntax (new Node) in favor of the direct syntax (Node->new). Remember - new is not a keyword, it's just a plain old method. The indirect syntax can get you into trouble because the compiler has to guess what you intend. Did you mean the new() function in the package you're in or the new() method for the next parseable chunk?

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: objects are references, right?
by Joost (Canon) on Jul 06, 2005 at 10:10 UTC
    Does the hash value $child->{parent} now hold the blessed hash that was created when I did $parent = new Node;, or a reference to it?
    It holds a reference to the blessed hash. I think the confusion comes in part from the fact that bless needs a reference argument, but the thing that is actually blessed is the data the reference points at.

    In fact, an object in perl is *not* a reference but a blessed variable (a scalar, hash, filehandle, etc.), but the only way you can usefully do anything with that object is through a reference to that variable - you can't call an instance method without a reference, and copying the data structure directly will not copy its "blessedness", but copying a reference to it will create a new reference to the same object:

    # create object of My::Class my $object = bless { some => 'thing' }, "My::Class"; # create a second reference to /the same/ object my $copy = $object; # copy object data - this /will not/ create a new object # but $copy2 will be a reference to an unblessed hash # containing all the data in $object my $copy2 = { %$object }; # if you really need to "clone" an object, you need # to bless the copy too, (and mind nested objects! - # I ignored those here) my $clone = bless { %$object }, "My::Package"

    Hope this helps :-)