in reply to object oriented tutorial question

Here is an Address.pm that works with your code:
#class Address package Address; use strict; use warnings; #constructor sub new { my ($class) = @_; my $self = { _street => undef, _city => undef, _state => undef, _zip => undef }; bless $self, $class; return $self; } sub street { my ( $self, $street ) = @_; $self->{_street} = $street if defined($street); return $self->{_street}; } sub city { my ( $self, $city ) = @_; $self->{_city} = $city if defined($city); return $self->{_city}; } sub state { my ( $self, $state ) = @_; $self->{_state} = $state if defined($state); return $self->{_state}; } sub zip { my ( $self, $zip ) = @_; $self->{_zip} = $zip if defined($zip); return $self->{_zip}; } sub print { my ($self) = @_; print "Address: $self->{_street}\n". "$self->{_city}\n" . "$self->{_state}\n" . "$self->{_zip}\n\n" ; } 1;

Replies are listed 'Best First'.
Re^2: object oriented tutorial question
by cdarke (Prior) on Sep 03, 2007 at 11:24 UTC
    And here is an "inside-out" version of the same. The attributes have their own hashes that are not exposed to the outside world, so the nasty users can only access them by calling a method. The "object" that they see is the address of a 'my' variable, which is useless to them.
    #class Address using inside-out objects package Address; use Scalar::Util qw(refaddr); use strict; use warnings; my %street; my %city; my %state; my %zip; #constructor sub new { my ($class, $street, $city, $state, $zip) = @_; # Get any old (unique) reference my $self = bless \do{my $gash}, $class; my $key = refaddr $self; # Extract the address $street{$key} = $street; $city {$key} = $city; $state {$key} = $state; $zip {$key} = $zip; return $self; } sub street { my ( $self, $street ) = @_; my $key = refaddr $self; $street{$key} = $street if defined($street); return $street{$key}; } sub city { my ( $self, $city ) = @_; my $key = refaddr $self; $city{$key} = $city if defined($city); return $city{$key}; } sub state { my ( $self, $state ) = @_; my $key = refaddr $self; $state{$key} = $state if defined($state); return $state{$key}; } sub zip { my ( $self, $zip ) = @_; my $key = refaddr $self; $zip{$key} = $zip if defined($zip); return $zip{$key}; } sub print { my ($self) = @_; my $key = refaddr $self; print "Address: $street{$key}\n". "$city{$key}\n" . "$state{$key}\n" . "$zip{$key}\n\n" ; } 1;
      Your inside-out implementation is missing the obligatory destructor.
      sub DESTROY { my $id = refaddr shift; delete $_->{ $id} for \ ( %street, %city, %state, %zip); }

      I'd like to contrast an implementation of the Address class based on the Alter module. It is itself hash-based and thus closer to the original hash-based implementation than the inside-out variant, while still offering the black-box-inheritance properties. Essentially, the changes are that the ego() function is called on the object before each access to the object data.

      #class Address (Alter-based) package Address; use strict; use warnings; use Alter ego => {}; # alter ego is a hash #constructor sub new { my ($class) = @_; my $self = \ my $o; # the object proper (a scalar ref) %{ ego $self } = ( # set up the ego for this class _street => undef, _city => undef, _state => undef, _zip => undef ); bless $self, $class; return $self; } sub street { my ( $self, $street ) = @_; ego( $self)->{_street} = $street if defined($street); return ego( $self)->{_street}; } sub city { my ( $self, $city ) = @_; ego( $self)->{_city} = $city if defined($city); return ego( $self)->{_city}; } sub state { my ( $self, $state ) = @_; ego( $self)->{_state} = $state if defined($state); return ego( $self)->{_state}; } sub zip { my ( $self, $zip ) = @_; ego( $self)->{_zip} = $zip if defined($zip); return ego( $self)->{_zip}; } sub print { print "Address: $_->{_street}\n". "$_->{_city}\n" . "$_->{_state}\n" . "$_->{_zip}\n\n" for ego shift; } 1;
      Anno
        Oops. Apologies.