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

merry christmas,
i had a problem with a module i wrote. as i´m quite new to OOP in perl please give me some explanations here. first i tried:
sub new{ my $self = shift; my $foo = shift; $self->{'foo'} = $foo; return bless( {}, ( ref($self) || $self ) ); }

this didn´t work, so i tried to
$self = bless( {}, ( ref($self) || $self ) ); $self->{'foo'} = $foo; return $self;

now it works, but i dont exactly know why. is this good style? is there a better whay to do this?

Replies are listed 'Best First'.
Re: $self->{foo} in sub new {}
by broquaint (Abbot) on Dec 22, 2003 at 13:27 UTC
    The problem is that you're treating $self as a hash, when in all likelihood it's a scalar containing the name of the class that invoked the new method e.g
    sub new { my $self = shift; print "I was invoked by: $self\n"; } main->new; __output__ I was invoked by: main
    What you really want is to create a new variable called $self and bless that (not an anonymous hashref, as you're currently doing) e.g
    { package demo; sub new { my($class, $foo) = @_; my $self = { foo => $foo }; return bless $self, $class; } } use Data::Dumper; my $obj = demo->new('a string'); print Dumper($obj); __output__ $VAR1 = bless( { 'foo' => 'a string' }, 'demo' );
    Now the new method blesses the $self variable into the class that invoked the method. For more information on OO in perl see perlboot and perltoot.
    HTH

    _________
    broquaint

      This is a request for further enlightenment.

      Since bless returns the blessed object, is there anything actually wrong with blessing the anonymous hash and assigning the result to $self?

      In fact, in your example, it appears that $self could be done away with entirely:

      sub new { my ($class, $foo) = @_; bless { foo => $foo } , $class; }
      I understand that if new gets more involved and does more stuff with the object being created, that it would be a good thing to have a variable to work with. But it seems that the variable could be created and blessed first, then stocked with goods, and then returned, and I don't see any harm in it, though it isn't the way things are usually done.
      sub new { my ($class, @args) = @_; my $self = bless {}, $class; # Do stuff with @args # ... # then return: $self; }
      Where's the line between convention and Cargo Cult? This hints at being a meditation, except I don't really have the answers.

      The PerlMonk tr/// Advocate
        I think in one posting I mentioned an even shorter constructor:
        sub new { bless {}, shift }
        But we're not golfing here.

        I see no problem in letting the return value of bless be the return value from a constructor, provided that there's no need to address the intermediate reference during the construction of the object.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

      It is usually a good idea to use the $class = ref($class) || $class so a new object can be created from an existing object.
      use strict; use Data::Dumper; package MyClass; sub new { my ($class, $foo) = @_; print __PACKAGE__ . "->new called with $class, $foo\n"; $class = ref($class) || $class; print "\$class is now $class\n\n"; my $self = {foo => $foo}; return bless $self, $class; } package main; my $obj1 = MyClass->new('fooval1'); my $obj2 = $obj1->new('fooval2'); print Dumper($obj1, $obj2); __END__ Outputs: MyClass->new called with MyClass, fooval1 $class is now MyClass MyClass->new called with MyClass=HASH(0x15d54bc), fooval2 $class is now MyClass $VAR1 = bless( { 'foo' => 'fooval1' }, 'MyClass' ); $VAR2 = bless( { 'foo' => 'fooval2' }, 'MyClass' );

      --

      flounder

        It is usually a good idea to use the $class = ref($class) || $class so a new object can be created from an existing object.

        It is? Why would you want to do a thing like that?

        Yes, Perl lets you do this sort of thing, but unless you're doing some rather unusual factory/exemplar style OO programming it should be avoided. It just makes Perl's objects look more mysterious than they are.

        Sometimes I have wished to clone an object, but that is another issue entirely.

        Certainly if you have lots of objects of different packages being created dynamically and delegated to other objects and the package name is not be readily available, then sure, this is the way to go, but I suspect that this is not the case here. Think of it from the caller's point of view: are they able to say PackageName->new($foo) instead of $pn->new($foo)? Usually the answer is yes, so the ref($class) trick is not needed.

Re: $self->{foo} in sub new {}
by drieux (Initiate) on Dec 22, 2003 at 20:47 UTC

    traditionally I would do:

    sub new { my $classs = shift; my $self = { foo => $_[0] }; # initiate the fooneff bless $self, $class; }
    the problem you ran into is several fold.
    1. your $self is the class being passed in
    2. you then convert it into a hash_ref
    3. you then bless an empty hash and retreat into an old dog

    Your work around is somewhat ingenous, since you re-use the $self in a creative way. But unless you really have a good reason to want to have a 'reference' passed in to your new() as an instance method, you really should avoid it.