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

Re: Perl Object Initilization

by PyrexKidd (Monk)
on Jun 09, 2011 at 19:34 UTC ( [id://908988]=note: print w/replies, xml ) Need Help??


in reply to Perl Object Initilization

Ah, HA! So I have to dereference $self to a hash then I can treat it as a hash. (DUH! right...)

I've always heard that it is bad practice to access an objects 'private' variables. I know this concept isn't enforced explicitly in Perl, but is there a good way to do this?

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; package Obj; sub new { my ($class, @args) = @_; my $self = {}; bless $self, $class; $self->init(@args); return $self; } sub init { my ($self, @args) = @_; %{$self} = ( a => 10, @args, ); return $self; } sub print_val_a { my $self = shift; # my $FHOUT = shift || "STDOUT"; # print $FHOUT $self->{'a'} . "\n"; print $self->{'a'} . "\n"; } package main; my $obj1 = Obj->new(); $obj1->print_val_a(); my $obj2 = Obj->new(a => 40); $obj2->print_val_a();

(Granted for some reason this: # my $FHOUT = shift || "STDOUT"; # print $FHOUT $self->{'a'} . "\n"; doesn't work as expected ...)

this works but then how do you control output direction? Is there a 'cleaner' way to do this?

and finally, how about destroying objects? according to perlobj, objects are destroyed automagically when they go out of scop, but what if I want to destroy them manually? as far as I can tell, calling a method DESTROY does not automatically destroy it... Is there even any reason to cleanup after your objects?

Replies are listed 'Best First'.
Re^2: Perl Object Initilization
by tospo (Hermit) on Jun 10, 2011 at 10:02 UTC
    you should not redefine $self once you have blessed it into objecthood. Assign to individual keys of the underlying hash instead. In addition to the method given by chromatic above, you can also do it this way (just a slightly different style):
    sub init { my $self = shift; my %args = @_; while (my ($attribute, $value) = each %args){ $self->{$attribute} = $value; } }
    Here yuo are using the fact that an even-sized list can simply be assigned to a new hash to populate it ( which is what you always do when you say my %hash=( key1 => value2 ) as '=>' is just a glorified comma).
    I would also agree that, particularly in this case, a separate init method is not needed, because you are just assigning values to attributes and that can all be done when you construct the hash that you then bless in the 'new' method.
    There may be some cases where more complicated setup needs to be done that might be better off in separate subs, such as connections to various databases, but then I would call them things like '_init_db_connection' or whatever you need to do.
    I would also second chromatic's suggestion to look into Moose soon. If you are just starting with OO programming in Perl then it's certainly good to see the non-Moose, old style first and understand it but then move on to a more modern object system like Moose. It seems like a bit of a learning curve at the beginning but it's well worth it.
      If you are just starting with OO programming in Perl then it's certainly good to see the non-Moose, old style first and understand it but then move on to a more modern object system like Moose.

      I think that's backwards, especially if you've not done OO before. Perl 5's default OO system exposes so much plumbing it's easy to get lost in the syntactic details of how to do things instead of understanding well what to do and why to do it.

      That's kind of like suggesting that you make your own pie crust by hand before you can ever put toppings on a bake at home pizza.

        absolutely, no way you can put toppings on pizze before you can do the crust!!! :)

      This is a simplified version.

      In this particular case, you are saying that it is better to pass a hash (or hash ref) and build any attributes/values (using a loop) because if you have an uneven list it will cause a mismatch of keys/values?

      on the note of 'initialize as needed', would you define the respective initialization subroutines in the class definition, then call them from the code where you require the object?

Re^2: Perl Object Initilization
by 7stud (Deacon) on Jun 11, 2011 at 20:15 UTC

    1) # my $FHOUT = shift || "STDOUT";

    Granted for some reason this: # my $FHOUT = shift || "STDOUT"; # print $FHOUT $self->{'a'} . "\n"; doesn't work as expected ...)

    "STDOUT" and "GOBBLEDYGOOK" are essentially equivalent: they are both strings--not filehandles.

    2)...and finally, how about destroying objects? according to perlobj, objects are destroyed automagically when they go out of scop, but what if I want to destroy them manually? as far as I can tell, calling a method DESTROY does not automatically destroy it... Is there even any reason to cleanup after your objects?

    There can be. If you have file handles or database connections you want to close. Or if you merely want to know when your objects are destroyed, you can print out a message. There are also more advanced reasons for calling DESTROY:

    see here

    perl calls DESTROY for you--just before perl is going to destroy the object. If you don't have a specific reason for defining a DESTROY method, then don't. perl will usually take care of everything for you.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-03-28 09:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found