This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
TODO addition by Jerry D. Hedden.
[perl5.git] / pod / perltoot.pod
index 90ef81a..4a212fb 100644 (file)
@@ -65,7 +65,7 @@ For example, let's make a simple Person class module.  It gets stored in
 the file Person.pm.  If it were called a Happy::Person class, it would
 be stored in the file Happy/Person.pm, and its package would become
 Happy::Person instead of just Person.  (On a personal computer not
-running Unix or Plan 9, but something like MacOS or VMS, the directory
+running Unix or Plan 9, but something like Mac OS or VMS, the directory
 separator may be different, but the principle is the same.)  Do not assume
 any formal relationship between modules based on their directory names.
 This is merely a grouping convenience, and has no effect on inheritance,
@@ -111,8 +111,8 @@ by up-casing the hash keys:
         PEERS => [ "Norbert", "Rhys", "Phineas"],
     };
 
-And so you could get at C<$rec-E<gt>{NAME}> to find "Jason", or
-C<@{ $rec-E<gt>{PEERS} }> to get at "Norbert", "Rhys", and "Phineas".
+And so you could get at C<< $rec->{NAME} >> to find "Jason", or
+C<< @{ $rec->{PEERS} } >> to get at "Norbert", "Rhys", and "Phineas".
 (Have you ever noticed how many 23-year-old programmers seem to
 be named "Jason" these days? :-)
 
@@ -224,23 +224,8 @@ The second argument is the class into which the referent will be blessed.
 By not assuming our own class as the default second argument and instead
 using the class passed into us, we make our constructor inheritable.
 
-While we're at it, let's make our constructor a bit more flexible.
-Rather than being uniquely a class method, we'll set it up so that
-it can be called as either a class method I<or> an object
-method.  That way you can say:
-
-    $me  = Person->new();
-    $him = $me->new();
-
-To do this, all we have to do is check whether what was passed in
-was a reference or not.  If so, we were invoked as an object method,
-and we need to extract the package (class) using the ref() function.
-If not, we just use the string passed in as the package name
-for blessing our referent.
-
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = {};
         $self->{NAME}   = undef;
         $self->{AGE}    = undef;
@@ -329,7 +314,7 @@ do more than fetch or set one particular field.
     sub exclaim {
         my $self = shift;
         return sprintf "Hi, I'm %s, age %d, working with %s",
-            $self->{NAME}, $self->{AGE}, join(", ", $self->{PEERS});
+            $self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}});
     }
 
 Or maybe even one like this:
@@ -401,8 +386,7 @@ it instead a file-scoped lexical, you should make these
 changes to your Person::new() constructor:
 
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = {};
         $Census++;
         $self->{NAME}   = undef;
@@ -425,6 +409,10 @@ this could be done:
 Notice how there's no memory to deallocate in the destructor?  That's
 something that Perl takes care of for you all by itself.
 
+Alternatively, you could use the Class::Data::Inheritable module from
+CPAN.
+
+
 =head2 Accessing Class Data
 
 It turns out that this is not really a good way to go about handling
@@ -454,8 +442,7 @@ a public data member in the same way that NAME, AGE, and PEERS are.
 to perl version 5.004 we'll have to quote the field name.)
 
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = {};
         $self->{NAME}     = undef;
         $self->{AGE}      = undef;
@@ -542,7 +529,7 @@ and DESTROY methods as follows:
     }
 
 What happens if a derived class (which we'll call Employee) inherits
-methods from this Person base class?  Then C<Employee-E<gt>debug()>, when called
+methods from this Person base class?  Then C<< Employee->debug() >>, when called
 as a class method, manipulates $Person::Debugging not $Employee::Debugging.
 
 =head2 Class Destructors
@@ -646,8 +633,7 @@ Ok.  To do this, we'll change Person::new() so that it supports
 a full name field this way:
 
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = {};
         $self->{FULLNAME} = Fullname->new();
         $self->{AGE}      = undef;
@@ -679,8 +665,7 @@ by the appropriate name to access them:
     use strict;
 
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = {
             TITLE       => undef,
             CHRISTIAN   => undef,
@@ -749,7 +734,7 @@ Finally, here's the test program:
     $him->fullname->title("St");
     $him->age(1);
 
-    printf "%s is really %s.\n", $him->name, $him->fullname;
+    printf "%s is really %s.\n", $him->name, $him->fullname->as_string;
     printf "%s's age: %d.\n", $him->name, $him->age;
     $him->happy_birthday;
     printf "%s's age: %d.\n", $him->name, $him->age;
@@ -816,7 +801,7 @@ What do we mean by the Person::new() function -- isn't that actually
 a method?  Well, in principle, yes.  A method is just a function that
 expects as its first argument a class name (package) or object
 (blessed reference).   Person::new() is the function that both the
-C<Person-E<gt>new()> method and the C<Employee-E<gt>new()> method end
+C<< Person->new() >> method and the C<< Employee->new() >> method end
 up calling.  Understand that while a method call looks a lot like a
 function call, they aren't really quite the same, and if you treat them
 as the same, you'll very soon be left with nothing but broken programs.
@@ -936,7 +921,8 @@ comes to the rescue here.
 This way it starts looking in my class's @ISA.  This only makes sense
 from I<within> a method call, though.  Don't try to access anything
 in SUPER:: from anywhere else, because it doesn't exist outside
-an overridden method call.
+an overridden method call. Note that C<SUPER> refers to the superclass of
+the current package, I<not> to the superclass of C<$self>.
 
 Things are getting a bit complicated here.  Have we done anything
 we shouldn't?  As before, one way to test whether we're designing
@@ -965,7 +951,7 @@ And here's the test program:
     $boss->age(47);
     $boss->peers("Frank", "Felipe", "Faust");
 
-    printf "%s is age %d.\n", $boss->fullname, $boss->age;
+    printf "%s is age %d.\n", $boss->fullname->as_string, $boss->age;
     printf "His peers are: %s\n", join(", ", $boss->peers);
 
 Running it, we see that we're still ok.  If you'd like to dump out your
@@ -1004,8 +990,7 @@ know about its immediate superclass, but never vice-versa.)  So let's
 fix up Employee::new() this way:
 
     sub new {
-        my $proto = shift;
-        my $class = ref($proto) || $proto;
+        my $class = shift;
         my $self  = $class->SUPER::new();
         $self->{SALARY}        = undef;
         $self->{ID}            = undef;
@@ -1124,12 +1109,11 @@ it happens when you say
 If you wanted to add version checking to your Person class explained
 above, just add this to Person.pm:
 
-    use vars qw($VERSION);
-    $VERSION = '1.1';
+    our $VERSION = '1.1';
 
-and then in Employee.pm could you can say
+and then in Employee.pm you can say
 
-    use Employee 1.1;
+    use Person 1.1;
 
 And it would make sure that you have at least that version number or
 higher available.   This is not the same as loading in that exact version
@@ -1240,8 +1224,7 @@ different:
     package Person;
 
     sub new {
-        my $that  = shift;
-        my $class = ref($that) || $that;
+        my $class  = shift;
         my $self = {
            NAME  => undef,
            AGE   => undef,
@@ -1363,7 +1346,7 @@ constructor will look like when taking this approach:
 
     package Person;
     use Carp;
-    use vars qw($AUTOLOAD);  # it's a package global
+    our $AUTOLOAD;  # it's a package global
 
     my %fields = (
        name        => undef,
@@ -1372,8 +1355,7 @@ constructor will look like when taking this approach:
     );
 
     sub new {
-       my $that  = shift;
-       my $class = ref($that) || $that;
+       my $class = shift;
        my $self  = {
            _permitted => \%fields,
            %fields,
@@ -1433,8 +1415,7 @@ Here's how to be careful:
     package Employee;
     use Person;
     use strict;
-    use vars qw(@ISA);
-    @ISA = qw(Person);
+    our @ISA = qw(Person);
 
     my %fields = (
        id          => undef,
@@ -1442,9 +1423,8 @@ Here's how to be careful:
     );
 
     sub new {
-       my $that  = shift;
-       my $class = ref($that) || $that;
-       my $self = bless $that->SUPER::new(), $class;
+       my $class = shift;
+       my $self  = $class->SUPER::new();
        my($element);
        foreach $element (keys %fields) {
            $self->{_permitted}->{$element} = $fields{$element};
@@ -1494,10 +1474,10 @@ Here's a simple example of using it:
     struct 'Fred' => {
         one        => '$',
         many       => '@',
-        profession => Jobbie,  # calls Jobbie->new()
+        profession => 'Jobbie',  # does not call Jobbie->new()
     };
 
-    $ob = Fred->new;
+    $ob = Fred->new(profession => Jobbie->new());
     $ob->one("hmmmm");
 
     $ob->many(0, "here");
@@ -1511,6 +1491,10 @@ You can declare types in the struct to be basic Perl types, or
 user-defined types (classes).  User types will be initialized by calling
 that class's new() method.
 
+Take care that the C<Jobbie> object is not created automatically by the
+C<Fred> class's new() method, so you should specify a C<Jobbie> object
+when you create an instance of C<Fred>.
+
 Here's a real-world example of using struct generation.  Let's say you
 wanted to override Perl's idea of gethostbyname() and gethostbyaddr() so
 that they would return objects that acted like C structures.  We don't
@@ -1560,16 +1544,15 @@ Here's the whole implementation:
 
     BEGIN {
        use Exporter   ();
-       use vars       qw(@EXPORT @EXPORT_OK %EXPORT_TAGS);
-       @EXPORT      = qw(gethostbyname gethostbyaddr gethost);
-       @EXPORT_OK   = qw(
-                          $h_name         @h_aliases
-                          $h_addrtype     $h_length
-                          @h_addr_list    $h_addr
-                      );
-       %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+       our @EXPORT      = qw(gethostbyname gethostbyaddr gethost);
+       our @EXPORT_OK   = qw(
+                              $h_name         @h_aliases
+                              $h_addrtype     $h_length
+                              @h_addr_list    $h_addr
+                          );
+       our %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
     }
-    use vars      @EXPORT_OK;
+    our @EXPORT_OK;
 
     # Class::Struct forbids use of @ISA
     sub import { goto &Exporter::import }
@@ -1649,8 +1632,7 @@ update value fields in the hash.  Convenient, eh?
 
     # this is the same as before...
     sub new {
-        my $that  = shift;
-        my $class = ref($that) || $that;
+        my $class = shift;
         my $self = {
            NAME  => undef,
            AGE   => undef,
@@ -1661,7 +1643,7 @@ update value fields in the hash.  Convenient, eh?
     }
 
     use Alias qw(attr);
-    use vars qw($NAME $AGE $PEERS);
+    our ($NAME, $AGE, $PEERS);
 
     sub name {
        my $self = attr shift;
@@ -1692,7 +1674,7 @@ update value fields in the hash.  Convenient, eh?
         return ++$AGE;
     }
 
-The need for the C<use vars> declaration is because what Alias does
+The need for the C<our> declaration is because what Alias does
 is play with package globals with the same name as the fields.  To use
 globals while C<use strict> is in effect, you have to predeclare them.
 These package variables are localized to the block enclosing the attr()
@@ -1703,7 +1685,7 @@ as with any other local().
 It would be nice to combine Alias with
 something like Class::Struct or Class::MethodMaker.
 
-=head2 NOTES
+=head1 NOTES
 
 =head2 Object Terminology
 
@@ -1730,7 +1712,7 @@ as a class or object method is by usage only.  You could accidentally
 call a class method (one expecting a string argument) on an
 object (one expecting a reference), or vice versa.
 
-Z<>From the C++ perspective, all methods in Perl are virtual.
+From the C++ perspective, all methods in Perl are virtual.
 This, by the way, is why they are never checked for function
 prototypes in the argument list as regular builtin and user-defined
 functions can be.
@@ -1753,27 +1735,31 @@ L<perltie>,
 and
 L<overload>.
 
-=head1 COPYRIGHT
+L<perlboot> is a kinder, gentler introduction to object-oriented
+programming.
+
+L<perltooc> provides more detail on class data.
+
+Some modules which might prove interesting are Class::Accessor,
+Class::Class, Class::Contract, Class::Data::Inheritable,
+Class::MethodMaker and Tie::SecureHash
+
 
-I I<really> hate to have to say this, but recent unpleasant
-experiences have mandated its inclusion:
-
-    Copyright 1996 Tom Christiansen.  All Rights Reserved.
-
-This work derives in part from the second edition of I<Programming Perl>.
-Although destined for release as a manpage with the standard Perl
-distribution, it is not public domain (nor is any of Perl and its docset:
-publishers beware).  It's expected to someday make its way into a revision
-of the Camel Book.  While it is copyright by me with all rights reserved,
-permission is granted to freely distribute verbatim copies of this
-document provided that no modifications outside of formatting be made,
-and that this notice remain intact.  You are permitted and encouraged to
-use its code and derivatives thereof in your own source code for fun or
-for profit as you see fit.  But so help me, if in six months I find some
-book out there with a hacked-up version of this material in it claiming to
-be written by someone else, I'll tell all the world that you're a jerk.
-Furthermore, your lawyer will meet my lawyer (or O'Reilly's) over lunch
-to arrange for you to receive your just deserts.  Count on it.
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright (c) 1997, 1998 Tom Christiansen 
+All rights reserved.
+
+This documentation is free; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+Irrespective of its distribution, all code examples in this file
+are hereby placed into the public domain.  You are permitted and
+encouraged to use this code in your own programs for fun
+or for profit as you see fit.  A simple comment in the code giving
+credit would be courteous but is not required.
+
+=head1 COPYRIGHT
 
 =head2 Acknowledgments