Hi Joseph.

Well, it's 01:00 here and I really should go to bed, but I'll take a
stab at this before I go.

R. Joseph Newton wrote:
> >
> > Well, you goaded me into it.  I finally decided to pull the spoon
> > off my tongue and try Perl OOP.  I must say, it is pretty painless.
> > I can get used to the C-style arrows, though I'd prefer to use a
> > dot operator as in C++, and the bless() function is only mildly
> > fetishistic.  All in all, object creation is pretty
> > straightforward, though.
> >
> > But...
> >
> > I can do this:
> >
> > #!/usr/bin/perl -w
> >
> > use strict;
> >
> > use Person;

Note that the Person.pm file has to be in one of the directories
in @INC for this to work.

> > my $person = Person::new("Newton", "R. Joseph");

No. You should be able to write:

    my $person = Person->new("Newton", "R. Joseph");

which will call

    my $person = Person::new('Person', "Newton", "R. Joseph");

so you need a slight change to your 'new' method.

> > $person->set_address("666 NoSpam way", "Eugene", "OR", "97402",
> >  "USA");
> > $person->{'Surname'} = "Johnson";     #this
> > $person->print_name();
> > $person->{'What the heck'} = "Jeez, this is a porous guy!";  # and this
> > print "$person->{'What the heck'}\n";
> >
> > Without anything preventing me.

Yes. But you won't know what's in the hash that forms the object
unless you look through the code. Encapsulation says that your
only knowledge of an API should be its external interface.

> > I am not at all sure that this is a good thing.

It is. A very good thing. It means you can do what you need
to without anything to stop you, but you have to be quite
deliberate about it if you do. C quite happy for you to stomp
over anything in your virtual address space, and unless you get
an access violation you won't know anything about it until
you start getting strange errors after your software's been
running for some time. As the Camel says:

    "...perl isn't obsessed with enforced privacy... a Perl module
    would prefer that you stayed out of its living room because
    you weren't invited, not because it has a shotgun."

If it were an easy thing to do /accidentally/ then I wouldn't
like it, but as it is I'm happy. A bit like having a 'goto' in case
I need it, but easy to avoid if I want to do things 'properly'.

> > Is there any way to construct a class so that member
> > data stays private?

Yes, using closures, but I wold forget about that now until you
can write a module that holds together.

> > This was the factor that kept me from
> > venturing into Perl OOP, and it still seems like it could lead to
> > problems if the only thing preventing this kind of external access
> > is the injuction "Don't do that!".

I've never seen a library module that enforces privacy, and they
seem to work OK!

> > package Person;
> >
> > use strict;
> > use warnings;
> > use Address;
> >
> > sub new {

It's common to allow all methods to be called as object methods
or class methods. 'new' is a common exception (because it doesn't
read well to write:

    my $object2 = new $object1;
rather than
    my $object2 = new Class;

the framework:

sub new {
    my $self = shift;
    my ($surname, $givenname) = @_;
    my $class = ref $self || $self;
    bless {surname => $surname, givenname => $givenname}, $class;
}

> >   my $self = {
> >     'Surname' => $_[0],
> >     'Given Name' => $_[1]
> >   };
> >   bless $self;

This is OK but won't allow inheritance. You need to bless the
new object into the class it was called with.

> > }
> >
> > sub print_name {
> >   my $self = shift;
> >   print "$self->{'Surname'}, ";
> >   print "$self->{'Given Name'}\n";
> >   return unless defined $self->{'Address'};
> > #  print "$self->{'Address'}->{'Street'}\n";
> > #  print "$self->{'Address'}->{'City'}, ";
> > #  print "$self->{'Address'}->{'State'}  ";
> > #  print "$self->{'Address'}->{'PostCode'}\n";
> > #  print "$self->{'Address'}->{'Country'}\n" if
> > #  defined $self->{'Address'}->{'Country'};
> >   $self->{'Address'}->print();
> > }

Yes. You could tidy up your hash accessing using slices
and 'join' but that's fine.

> > sub set_address {
> >   my $self = shift;
> >   my $address = Address::new(@_);

    my $address = new Address (@_);

> > #  $address{'Street'} = $_[0];
> > #  $address{'City'} = $_[1] if defined $_[1];
> > #  $address{'State'} = $_[2] if defined $_[2];
> > #  $address{'PostCode'} = $_[3] if defined $_[3];
> > #  $address{'Country'} = $_[4] if defined $_[4];
> >   $self->{'Address'} = $address;

Well yes, but:


    $self->{'Address'} = new Address (@_);

(you could even drop the (@_) at the end, because a
subroutine without a parameter list will be passed @_
by default).

> > }
> >
> > #my $conclusion = "Person has a name";
> > 1;
> > __END__
> >
>
>
>
> > package Address;
> >
> > use strict;
> > use warnings;
> >
> > sub new {
> >   my $self = {
> >     'Street' => $_[0],
> >   };
> >   $self->{'City'} = $_[1] if defined $_[1];
> >   $self->{'State'} = $_[2] if defined $_[2];
> >   $self->{'PostCode'} = $_[3] if defined $_[3];
> >   $self->{'Country'} = $_[4] if defined $_[4];
> >   bless $self;

    my $self = shift;
    my $class = ref $self || $self;

    $self = {};
    @{$self}{qw( City State PostCode Country )} = @_;

    bless $self, $class;

> > }
> >
> > sub print {
> >   my $self = shift;
> >   print "$self->{'Street'}\n";
> >   print "$self->{'City'}, ";
> >   print "$self->{'State'}  ";
> >   print "$self->{'PostCode'}\n";
> >   print "$self->{'Country'}\n" if
> >   defined $self->{'Country'};

    my $self = shift;
    my @data = @{$self}{qw( City State PostCode Country )};
    print "$_\n" foreach grep defined, @data;

> > }
> >
> > my $exultation = 'Whee-haw!!  we got adrresses, podner!';
> > __END__

Well done. Keep up the good work!

Rob




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to