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

As I noted in a previous post 175510 I am writing a simple Set object. However... I've hit a problem. Code is below then I explain:

package Abh::SimpleSet; sub new { my $self = {}; bless $self; return $self; } sub add { my ($self, $item) = @_; $self{$item} = undef; } sub remove { my ($self, $item) = @_; delete($self{$item}); } sub contains { my ($self, $item) = @_; return exists($self{$item}); } sub to_string { my $self = shift; return $class, "(" . join (", ", keys %self) . ")"; } sub union { my ($self, $otherSet) = @_; foreach $key (keys %otherSet) { $self{$key} = undef; } } # Must return true 1;

When I run the following using the above module...

use Abh::SimpleSet; $set1 = Abh::SimpleSet->new(); $set2 = Abh::SimpleSet->new(); $set1->add("a"); $set1->add("b"); $set1->add("c"); print "Set 1: " . $set1->to_string() . "\n"; $set2->add("d"); $set2->add("e"); $set2->add("f"); print "Set 2: " . $set2->to_string() . "\n";

... I get this output.

Set 1: (a, b, c) Set 2: (e, f, a, b, c, d)

I was expecting set 2 to contain just (d, e, f)... can someone help? I'm sure its a simple problem, but I checked the various OO tutorials and perlobj docs to no avail :(

Thanks,

____________
Arun

Replies are listed 'Best First'.
•Re: Problem with My New Perl Object
by merlyn (Sage) on Jun 18, 2002 at 22:22 UTC
Re: Problem with My New Perl Object
by dws (Chancellor) on Jun 18, 2002 at 22:32 UTC
    Though not the source of your problem, it's a good habit to use the class (package) name that's passed to the constructor, rather than taking the default. Using the passed package name allows you to use the inherited constructor if your class is subclassed.

    That is, write

    sub new { my $pkg = shift; my $self = bless {}, $pkg;
    instead of
    sub new { my $self = {}; bless $self;
      To make even neater write:

      sub new { my $pkg = shift; return bless {}, ref $pkg || $pkg; }
      to be able to pull off tricks like this:

      use strict; use warnings; package BaseClass; sub new { my $pkg = shift; bless {}, ref $pkg || $pkg; } sub bar { $_[0]->{'BaseClass::bar'} = $_[1]; } package SubClass; our @ISA = qw/BaseClass/; package main; my $obj = SubClass->new; my $foo = $obj->new; printf "obj isa %s\nfoo isa %s\n", $obj, $foo;

      Using the  bless {}, ref $pkg || $pkg idiom you are writing classes that are safe to subclass.

      Do have a look at Damian Conways excellent book Object Oriented Perl

      Kay

        To make even neater write:
        return bless {}, ref $pkg || $pkg;

        This technique has been the basis of at least one recent "cargo cult" discussion. There are mixed opinions over whether overloading a class constructor is a prudent thing to do.

        In this post, merlyn points out a cleaner way to get the same effect, without overloading your class constructor.