This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldiag: rewording
[perl5.git] / pod / perltoot.pod
index 594cb99..0d8648b 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,
@@ -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;
@@ -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;
@@ -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;
@@ -812,7 +797,7 @@ to do that.  There's a bit of package data used in the constructor,
 but the reference to this is stored on the object itself and all other
 methods access package data via that reference, so we should be ok.
 
-What do we mean by the Person::new() function -- isn't that actually
+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
@@ -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;
@@ -1031,7 +1016,8 @@ dubiously-OO languages like C++.
 The way it works is actually pretty simple: just put more than one package
 name in your @ISA array.  When it comes time for Perl to go finding
 methods for your object, it looks at each of these packages in order.
-Well, kinda.  It's actually a fully recursive, depth-first order.
+Well, kinda.  It's actually a fully recursive, depth-first order by
+default (see L<mro> for alternate method resolution orders).
 Consider a bunch of @ISA arrays like this:
 
     @First::ISA    = qw( Alpha );
@@ -1126,15 +1112,75 @@ above, just add this to Person.pm:
 
     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
 number.  No mechanism currently exists for concurrent installation of
 multiple versions of a module.  Lamentably.
 
+=head2 Deeper UNIVERSAL details
+
+It is also valid (though perhaps unwise in most cases) to put other
+packages' names in @UNIVERSAL::ISA.  These packages will also be
+implicitly inherited by all classes, just as UNIVERSAL itself is.
+However, neither UNIVERSAL nor any of its parents from the @ISA tree
+are explicit base classes of all objects.  To clarify, given the
+following:
+
+    @UNIVERSAL::ISA = ('REALLYUNIVERSAL');
+
+    package REALLYUNIVERSAL;
+    sub special_method { return "123" }
+
+    package Foo;
+    sub normal_method { return "321" }
+
+Calling Foo->special_method() will return "123", but calling
+Foo->isa('REALLYUNIVERSAL') or Foo->isa('UNIVERSAL') will return
+false.
+
+If your class is using an alternate mro like C3 (see
+L<mro>), method resolution within UNIVERSAL / @UNIVERSAL::ISA will
+still occur in the default depth-first left-to-right manner,
+after the class's C3 mro is exhausted.
+
+All of the above is made more intuitive by realizing what really
+happens during method lookup, which is roughly like this
+ugly pseudo-code:
+
+    get_mro(class) {
+        # recurses down the @ISA's starting at class,
+        # builds a single linear array of all
+        # classes to search in the appropriate order.
+        # The method resolution order (mro) to use
+        # for the ordering is whichever mro "class"
+        # has set on it (either default (depth first
+        # l-to-r) or C3 ordering).
+        # The first entry in the list is the class
+        # itself.
+    }
+
+    find_method(class, methname) {
+        foreach $class (get_mro(class)) {
+            if($class->has_method(methname)) {
+                return ref_to($class->$methname);
+            }
+        }
+        foreach $class (get_mro(UNIVERSAL)) {
+            if($class->has_method(methname)) {
+                return ref_to($class->$methname);
+            }
+        }
+        return undef;
+    }
+
+However the code that implements UNIVERSAL::isa does not
+search in UNIVERSAL itself, only in the package's actual
+@ISA.
+
 =head1 Alternate Object Representations
 
 Nothing requires objects to be implemented as hash references.  An object
@@ -1239,8 +1285,7 @@ different:
     package Person;
 
     sub new {
-        my $that  = shift;
-        my $class = ref($that) || $that;
+        my $class  = shift;
         my $self = {
            NAME  => undef,
            AGE   => undef,
@@ -1371,8 +1416,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,
@@ -1440,9 +1484,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};
@@ -1492,10 +1535,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");
@@ -1509,6 +1552,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
@@ -1646,8 +1693,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,
@@ -1750,17 +1796,23 @@ L<perltie>,
 and
 L<overload>.
 
+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
+
+
 =head1 AUTHOR AND COPYRIGHT
 
 Copyright (c) 1997, 1998 Tom Christiansen 
 All rights reserved.
 
-When included as part of the Standard Version of Perl, or as part of
-its complete documentation whether printed or otherwise, this work
-may be distributed only under the terms of Perl's Artistic License.
-Any distribution of this file or derivatives thereof I<outside>
-of that package require that special arrangements be made with
-copyright holder.
+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