in reply to how to code a class and use it with hash of hash as data member?

edward--

I've never done any object-oriented Perl before, so please bear with me. I've been meaning to teach myself OOPerl, so I thought I'd give it a shot.

Anyway, I've cleaned up some syntax errors in your code, and munged some stuff around, and came up with something that seems to work. I'm using a trivial test program:
#!/usr/bin/perl -w use strict; use myObject; my $T = myObject->new(); # We add a server by passing in the server name, and a hash ref of the # credentials we want to add $T->addServer('barrabas', { password=>"sa", hostname=>"devo.marcorp.or +g" }); $T->printMe; $T->deleteServer('default'); $T->printMe; $T->removeServerMap; $T->printMe;
The touched-up version of your code follows. Please note that I expect that there are some serious problems with it yet, as I haven't done this before. However, it will at least run with my test program.

When some guru comes by and notices something, please be kind... ;^)
package myObject; $VERSION = 1.00; use strict; use warnings; use diagnostics; use vars qw(@ISA); use Carp (); $Carp::Verbose =1; { my %serverMap = ( default => { ipaddress => "127.0.0.1", dsn => "default", userid => "sa", password => "password", instance => "instance" } ); sub new { my ($slf, %args) = @_; my %array=(); %array = (%args); #? my $self={}; return bless $self; } sub printMe() { my ($self) = @_; print "------ Available Servers ------\n"; for my $server (keys %serverMap) { print "\nServer: ", $server, "\n"; my $hr = $serverMap{$server}; for my $cr (keys %{$serverMap{$server}}) { print "\t$cr => $serverMap{$server}{$c +r}\n"; } } } sub addServer() { my ($self, $srvName, $hrCreds) = @_; $serverMap{$srvName} = $hrCreds; } sub removeServerMap($) { my ($self) = @_; %serverMap = (); } sub deleteServer($){ my ($self, $srvName) = @_; delete $serverMap{$srvName}; } } 1
--roboticus

Replies are listed 'Best First'.
Re^2: how to code a class and use it with hash of hash as data member?
by chromatic (Archbishop) on Mar 17, 2006 at 08:38 UTC

    That's close, but you can only ever have one "object" at a time, as you're using package-level data. That means you have to access the data in the object, not in the server map. You also don't need the prototypes on methods, as they're useless here.

    package myObject; use strict; use warnings; use vars '$VERSION'; $VERSION = 1.00; my %serverMap = ( default => { ipaddress => "127.0.0.1", dsn => "default", userid => "sa", password => "password", instance => "instance" } ); # use the arguments in $serverMap{ default } as attribute defaults sub new { my $class = shift; my %self = ( %{ $serverMap{ default } }, @_ ); bless \%self, $class; } sub printMe { my $self = shift; print "------ Available Servers ------\n"; for my $server ( keys %$self ) { print "\nServer: ", $server, "\n"; for my $cr ( keys %{ $self->{$server} } ) { print "\t$cr => $self->{$server}{$cr}\n"; } } } sub addServer { my ( $self, $srvName, $hrCreds ) = @_; $self->{$srvName} = $hrCreds; } sub removeServerMap { my $self = shift; %$self = (); } sub deleteServer { my ( $self, $srvName ) = @_; delete $self->{$srvName}; } 1;

    Update: Fixed a typo in the code.

      i guess I am hugely confuse about when to use $self->...
      in the first reply to my question, the code uses the
      %serverMap directly in each of the methods.. i guess because i define it outside all methods, it is visible???...
      but in yours, you use $self to access to it.
      another question of mine: i se eyou make a new constructor (more compact one), but
      don't quite get what it does? your decision for the change? my original verison has this package @ISA CLASS::Singleton...
      to prevent users of this class to have more than 1 copy of serverMap
      .. but from your comment in your psot, is that step necessary anymore? thanks

        The purpose of using $self is so that you can have more than one object, each with its own member data. The original code allowed people to create multiple objects, but each accessed the same hash. I don't see any real reason to use objects in that case.

        My $self doesn't access %serverMap. Each object gets its own copy of that data.

        I changed my constructor to throw out unnecessary code and to allow inheritance by using the two-argument form of bless, which is almost always the right thing to do.

        My code doesn't create a singleton, but I wasn't sure if you needed that.

      thanks for your reply. i wans thinking of using this as the
      datastructure to collect the mssql server credentials then
      issues sql statements to test against various data already
      in the database. we will enver use live database as it is a
      app that depends on a fresh installed embedded msdn or a
      new or existing sql server. we have a set of sample
      inputs, and want to do some query against the databse to
      make sure the data has been inserted into the database.
      but since there may be schema, change I was thinking about
      using object
      relational mapping to map my test code against the SQL..
      but is there a similar test framewrok arleady exits? since this is a common problem, I
      have a feeling I may be duplicating someone else work. I
      cannot use MOCK database as the dev team only support MSSQL and MSDN. any suggestion?