Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

OO doesn't seem to play nice with multiple instances

by krisahoch (Deacon)
on Jun 01, 2005 at 21:00 UTC ( #462656=perlquestion: print w/replies, xml ) Need Help??

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

Hey all,
It has been a while since I have posted, because well I have had nothing to say. This post is a plea for an RTFM Direction, or a 'Yeah, that sucks, try this'. I have written quite a bit of Code where I will use multiple instances of the same Object. The funny thing is that it seems the all of the instances have the same instance data as the last Object that was instatiated. Here is an example.
use strict; { package Interesting; my $_name = ''; sub new { my $proto = shift(); my $class = ref($proto) || $proto; my $this = bless({},$class); return $this; } sub myNameIs{ my ($this,$name) = @_; die("Don't tell me that I don't have a name.") unless(defined($nam +e)); $_name = $name; } sub whoAmI{ return($_name); } } my $one = new Interesting(); $one->myNameIs('What'); my $two = new Interesting(); $two->myNameIs('Who'); my $three = new Interesting(); $three->myNameIs('tukatukatuka SlimShady'); print "My name is : " . $one->whoAmI() . "\n"; print "My name is : " . $two->whoAmI() . "\n"; print "My name is : " . $three->whoAmI() . "\n";
Please tell me what I am doing wrong. Thank you, Kristofer

Replies are listed 'Best First'.
Re: OO doesn't seem to play nice with multiple instances
by diotalevi (Canon) on Jun 01, 2005 at 21:08 UTC

    Store the name in the $this/$self object, not in the global $_name. $_name was a single variable shared between multiple objects and thus you were always overwriting the value whenever you called myNameIs.

    package Interesting; sub new { my ( $class ) = @_; return bless {}, $class; } sub myNameIs{ my ( $self, $name ) = @_; defined $name or die "Don't tell me that I don't have a name."; # Store the name into the object return $self->{name} = $name; } sub whoAmI{ my ( $self ) = @_; # Retrieve the name from the object. return $self->{name}; }

    Separately, I would like to urge you to stop using the syntax $one = new Interesting in favor of $one = Interesting->new. There are some tricky bugs related to the first syntax and you can avoid that entire class of errors by just not using that syntax. If there were a new() function in the same package as the code which had new Interesting, then instead of calling Interesting::new( 'Interesting' ) it would call WhateverPackage::new( 'Interesting' ). In OO code, if you had another class with a method named new(), then you might find that the incorrect new() method was being called.

Re: OO doesn't seem to play nice with multiple instances
by Transient (Hermit) on Jun 01, 2005 at 21:07 UTC
    your $_name is essentially a package variable.

    If you want it tied to each instance, relate it to $this, e.g.:
    sub myNameIs { ... #$_name = $name; don't to this, everyone will have the same name $this->{name} = $name; ... }
    likewise on whoAmI.

    (...gives merlyn the honor post about ref($proto) || $proto)
Re: OO doesn't seem to play nice with multiple instances
by gellyfish (Monsignor) on Jun 01, 2005 at 21:09 UTC

    I would suggest storing the name in the hash you are using as the object - like with a key such as '_name'. You can then change your methods like:

    sub myNameIs{ my ($this,$name) = @_; die("Don't tell me that I don't have a name.") unless(defined($nam +e)); $this->{_name} = $name; } sub whoAmI{ my ($this ) = @_; return($this->{_name}); }
    The way that you are using the $_name is like having a static variable in other languages.

    /J\

Re: OO doesn't seem to play nice with multiple instances
by tlm (Prior) on Jun 01, 2005 at 21:12 UTC

    The problem is you are using a package-scoped variable ($_name) to store instance data instead of storing it in the object itself. Your methods should be closer to

    sub myNameIs{ my ($this,$name) = @_; die("Don't tell me that I don't have a name.") unless(defined($nam +e)); $this->{_name} = $name; } sub whoAmI{ my $this = shift; return($this->{_name}); }
    See perltoot for a tutorial of Perl OOP.

    the lowliest monk

Re: OO doesn't seem to play nice with multiple instances
by eric256 (Parson) on Jun 01, 2005 at 22:00 UTC

    FYI in Perl6 (Pugs right now) you can do this as follows:

    use v6; class Interesting { has $.name; method myNameIs ($name) { die "Don't tell me that I don't have a name." unless defined $name; $.name = $name; } method whoAmI () { return $.name; } } my $one = Interesting.new; $one.myNameIs('What'); my $two = Interesting.new; $two.myNameIs('Who'); my $three = Interesting.new(:name('tukatukatuka SlimShady')); say "My name is : " ~ $_.whoAmI() for ($one, $two,$three);

    ___________
    Eric Hodges
Re: OO doesn't seem to play nice with multiple instances
by krisahoch (Deacon) on Jun 01, 2005 at 21:12 UTC
    Thanks guys,
    That was the problem. Disclaimer: I have been running Java for a long time (notice the '$this' instead of '$self'?) and moved back in with Java habits.

    Upvotes all around.
    Kristofer
Re: OO doesn't seem to play nice with multiple instances
by Anonymous Monk on Jun 02, 2005 at 06:48 UTC
    I have written quite a bit of Code where I will use multiple instances of the same Object. The funny thing is that it seems the all of the instances have the same instance data as the last Object that was instatiated.
    You probably meant to say is multiple instances of the same Class.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2022-05-16 19:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (63 votes). Check out past polls.

    Notices?