Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re^7: Perl "new" command

by tobyink (Abbot)
on Mar 01, 2012 at 13:42 UTC ( #957219=note: print w/replies, xml ) Need Help??


in reply to Re^6: Perl "new" command
in thread Perl "new" command

... Now what? ...

can be replaced by:

bless do { my %self = (%{Colour->new($colour)}, %{Age->new($age)}); \% +self }, $class;

Moose (and some of its imitators) thankfully handles all of this for you. The Moose philosophy is to never write your own new method - rely on Moose to take care of it for you. If you do need to do some initialisation, then create a BUILD method - no matter how complex the inheritance you're using, Moose should call all the BUILD methods in a sane order.

The other solution is to go the inside-out object route. If your class doesn't care about the contents of the reference, then all is fine and dandy. The reference doesn't even have to be a hash/array any more - it could be a scalarref, a coderef, a quoted regexp, etc. Inside-out objects have been traditionally fiddly to write without leaking memory, but the recent "fieldhashes" modules have made it a lot easier.

Replies are listed 'Best First'.
Re^8: Perl "new" command
by JavaFan (Canon) on Mar 01, 2012 at 16:17 UTC
    bless do { my %self = (%{Colour->new($colour)}, %{Age->new($age)}); \% +self }, $class;
    So, you break encapsulation, and will depend on how things are implemented. If you're willing to break encapsulation, why even bother with OO?
    The other solution is to go the inside-out object route. If your class doesn't care about the contents of the reference, then all is fine and dandy.
    Inside-out objects aren't a silver bullet, and won't save the naive programmer.
    package Colour { use Scalar::Util 'refaddr'; my %colour; sub new { my $o = bless \do{my $var}, $_[0]; $colour{refaddr $o} = $_[1]; $o; } sub colour {$colour{refaddr $_[0]}} }; package Age { use Scalar::Util 'refaddr'; my %age; sub new { my $o = bless \do{my $var}, $_[0]; $age{refaddr $o} = $_[1]; $o; } sub age {$age{refaddr $_[0]}} }; package Colour_and_Age { our @ISA = qw[Age Colour]; use Scalar::Util 'refaddr'; sub new { my ($class, $colour, $age) = @_; ... Now what? ... } }
    Packages Colour and Age are written as inside-out objects, but because the same method constructs and initializes the object, the author of Colour_and_Age is screwed. He doesn't even have the luxury of breaking encapsulation.

    Now, if one separates object construction and object initialization, for instance:

    use Scalar::Util 'refaddr'; package Colour { use Scalar::Util 'refaddr'; my %colour; sub new {bless \do{my $var}, $_[0]} sub init {$colour{refaddr $_[0]} = $_[1]; $_[0]} sub colour {$colour{refaddr $_[0]}} }; package Age { use Scalar::Util 'refaddr'; my %age; sub new {bless \do{my $var}, $_[0]} sub init {$age{refaddr $_[0]} = $_[1]; $_[0]} sub age {$age{refaddr $_[0]}} };
    then one can use multiple inheritance without any problem:
    package Colour_and_Age { use Scalar::Util 'refaddr'; our @ISA = qw[Age Colour]; sub new {bless \do{my $var}, $_[0]} sub init ( my ($self, $colour, $age) = @_; $self->Colour::init($colour); $self->Age::init($age); $self; } }; my $o = Colour_and_Age::->new->init(red => 42);
    It only takes a few more keystrokes to create your classes that way, and you aren't robbing any users from using your classes with multiple inheritance. Also note you don't need inside-out objects to separate constructions and initialization.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2018-10-17 05:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...














    Results (90 votes). Check out past polls.

    Notices?