http://qs321.pair.com?node_id=219378


in reply to Re: Re: Tutorial: Introduction to Object-Oriented Programming
in thread Tutorial: Introduction to Object-Oriented Programming

I'm a little unclear as to whether you feel that I should simply have put in use strict in all my examples, or whether your are pointing out that using a hash_ref will not enable use strict to contribute much towards debugging, or both.
No, I'm wasn't saying you should use strict in your examples. That would be pointless drivel. I'm pointing out that if you use hash keys as attributes you will not benefit from using strict. But using strict is a good practise so why advocate a coding style that cannot benefit from it.
With respect to hiding (full encapsulation via anonymous subroutines) I feel quite strongly that this belongs in an advanced OO tutorial such as this one. I don't believe that throwing closures into the mix will help people learn the fundamentals of how objects work in Perl.
Where did I say full encapsulation can only be done with anonymous subroutines? Full encapsulation doesn't belong in an advanced tutorial. Full encapsulation is where you start. It's just like driving a car. Avoiding pedestrians isn't "advanced driving" - it's part of the basics. And you can get full (data) encapulation with techniques no more difficult that using hash references.
This ties into my feeling that, while hashes have their limitations, they are the easiest way to introduce someone to OO in Perl. Are they ideal? No. Are they less complicated than arrays or closures? Yes. Again, this was never meant to be the canonical OO tutorial, just an introduction.
Did I say you need to use arrays or closures? No. Do I think you can avoid the limitations I pointed out only by using arrays or closures instead of hashes? No. I'd still use hashes.

Here's how you can write the Quote class you used in your tutorial.

package Quote; use strict; use warnings; my (%phrase, %author, %approved); sub new { bless [] => shift; # Any reference will do. } sub set_phrase { my $self = shift; my $phrase = shift; $phrase {$self} = $phrase; } sub get_phrase { my $self = shift; return $phrase {$self}; } sub set_author { my $self = shift; my $author = shift; $author {$self} = $author; } sub get_author { my $self = shift; return $author {$self}; } sub is_approved { my $self = shift; @_ ? $approved {$self} = shift : $approved {$self}; } sub DESTROY { my $self = shift; delete $phrase {$self}; delete $author {$self}; delete $approved {$self}; }

Doesn't this remarkably look like your code? Perhaps my code is even simpler, I hardly use references - only the constructor returns a reference, but we don't care what it is, or how to put data in it (or to get something out of it). The only addition is the DESTROY function. But this code is using full encapsulation. Attributes cannot be trampled over. We're not enforcing our implementation on an inheriting class. We don't even care how an inherited class is implemented (if we are inherited, or we inherit something else, we don't need our constructor to be called - cool, isn't?)

I'm convinced this way of implementing classes is actually easier to learn, and less error-phrone than the traditional "just dump everything in the same place" way by using a hashref.

Abigail