diff options
Diffstat (limited to 'pod/perlboot.pod')
-rw-r--r-- | pod/perlboot.pod | 177 |
1 files changed, 56 insertions, 121 deletions
diff --git a/pod/perlboot.pod b/pod/perlboot.pod index ff6f1afcd1..8eaac8663e 100644 --- a/pod/perlboot.pod +++ b/pod/perlboot.pod @@ -44,8 +44,8 @@ packages, and called using the full package name. So let's create an entire pasture: # Cow::speak, Horse::speak, Sheep::speak as before - my @pasture = qw(Cow Cow Horse Sheep Sheep); - foreach my $animal (@pasture) { + @pasture = qw(Cow Cow Horse Sheep Sheep); + foreach $animal (@pasture) { &{$animal."::speak"}; } @@ -58,10 +58,10 @@ This results in: a Sheep goes baaaah! Wow. That symbolic coderef de-referencing there is pretty nasty. -We're counting on L<strict|C<no strict refs>> mode, certainly not -recommended for larger programs. And why was that necessary? Because -the name of the package seems to be inseparable from the name of the -subroutine we want to invoke within that package. +We're counting on C<no strict subs> mode, certainly not recommended +for larger programs. And why was that necessary? Because the name of +the package seems to be inseparable from the name of the subroutine we +want to invoke within that package. Or is it? @@ -87,13 +87,12 @@ And once again, this results in: That's not fun yet. Same number of characters, all constant, no variables. But yet, the parts are separable now. Watch: - my $a = "Cow"; + $a = "Cow"; $a->speak; # invokes Cow->speak Ahh! Now that the package name has been parted from the subroutine name, we can use a variable package name. And this time, we've got -something that works even when L<strict|C<use strict refs>> is -enabled. +something that works even when C<use strict refs> is enabled. =head2 Invoking a barnyard @@ -110,8 +109,8 @@ example: print "a Sheep goes baaaah!\n" } - my @pasture = qw(Cow Cow Horse Sheep Sheep); - foreach my $animal (@pasture) { + @pasture = qw(Cow Cow Horse Sheep Sheep); + foreach $animal (@pasture) { $animal->speak; } @@ -169,14 +168,11 @@ the same class. Let's call out from C<speak> to a helper method called C<sound>. This method provides the constant text for the sound itself. - { - package Cow; - + { package Cow; sub sound { "moooo" } - sub speak { - my $class = shift; - print "a $class goes ", $class->sound, "!\n" + my $class = shift; + print "a $class goes ", $class->sound, "!\n" } } @@ -184,11 +180,8 @@ Now, when we call C<< Cow->speak >>, we get a C<$class> of C<Cow> in C<speak>. This in turn selects the C<< Cow->sound >> method, which returns C<moooo>. But how different would this be for the C<Horse>? - { - package Horse; - + { package Horse; sub sound { "neigh" } - sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n" @@ -204,9 +197,7 @@ Horse? Yes, with inheritance! We'll define a common subroutine package called C<Animal>, with the definition for C<speak>: - { - package Animal; - + { package Animal; sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n" @@ -216,12 +207,8 @@ definition for C<speak>: Then, for each animal, we say it "inherits" from C<Animal>, along with the animal-specific sound: - { - package Cow; - - # Not safe under `use strict', see below + { package Cow; @ISA = qw(Animal); - sub sound { "moooo" } } @@ -269,34 +256,32 @@ The easiest is to just spell the package name out: Or allow it as an implicitly named package variable: package Cow; - our @ISA = qw(Animal); + use vars qw(@ISA); + @ISA = qw(Animal); If you're bringing in the class from outside, via an object-oriented module, you change: package Cow; use Animal; - our @ISA = qw(Animal); + use vars qw(@ISA); + @ISA = qw(Animal); into just: package Cow; use base qw(Animal); -And that's pretty darn compact. Read about the L<base|base> pragma. +And that's pretty darn compact. =head2 Overriding the methods Let's add a mouse, which can barely be heard: - # Animal package that we wrote before, goes here - { - package Mouse; - - our @ISA = qw(Animal); - + # Animal package from before + { package Mouse; + @ISA = qw(Animal); sub sound { "squeak" } - sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n"; @@ -324,14 +309,10 @@ C<Animal> does, but add in the extra comment? Sure! First, we can invoke the C<Animal::speak> method directly: - # Animal package that we wrote before, goes here - { - package Mouse; - - our @ISA = qw(Animal); - + # Animal package from before + { package Mouse; + @ISA = qw(Animal); sub sound { "squeak" } - sub speak { my $class = shift; Animal::speak($class); @@ -364,11 +345,8 @@ A better solution is to tell Perl to search from a higher place in the inheritance chain: # same Animal as before - { - package Mouse; - + { package Mouse; # same @ISA, &sound as before - sub speak { my $class = shift; $class->Animal::speak; @@ -394,11 +372,8 @@ invocation, we get a search of all of our super classes (classes listed in C<@ISA>) automatically: # same Animal as before - { - package Mouse; - + { package Mouse; # same @ISA, &sound as before - sub speak { my $class = shift; $class->SUPER::speak; @@ -417,7 +392,7 @@ So far, we've seen the method arrow syntax: or the equivalent: - my $a = "Class"; + $a = "Class"; $a->method(@args); which constructs an argument list of: @@ -444,20 +419,14 @@ haven't even begun to cover. Let's start with the code for the C<Animal> class and the C<Horse> class: - { - package Animal; - + { package Animal; sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n" } } - - { - package Horse; - - our @ISA = qw(Animal); - + { package Horse; + @ISA = qw(Animal); sub sound { "neigh" } } @@ -479,7 +448,7 @@ An "instance" is generally created by a class. In Perl, any reference can be an instance, so let's start with the simplest reference that can hold a horse's name: a scalar reference. - my $name = "Mr. Ed"; + my $name = "Mr. Ed"; my $talking = \$name; So now C<$talking> is a reference to what will be the instance-specific @@ -530,13 +499,9 @@ Because we get the instance as the first parameter, we can now access the instance-specific data. In this case, let's add a way to get at the name: - { - package Horse; - - our @ISA = qw(Animal); - + { package Horse; + @ISA = qw(Animal); sub sound { "neigh" } - sub name { my $self = shift; $$self; @@ -565,21 +530,16 @@ guts" of a Horse are visible. That's good if you're a veterinarian, but not if you just like to own horses. So, let's let the Horse class build a new horse: - { - package Horse; - - our @ISA = qw(Animal); - + { package Horse; + @ISA = qw(Animal); sub sound { "neigh" } - sub name { my $self = shift; $$self; } - sub named { my $class = shift; - my $name = shift; + my $name = shift; bless \$name, $class; } } @@ -610,31 +570,23 @@ But was there anything specific to C<Horse> in that method? No. Therefore, it's also the same recipe for building anything else that inherited from C<Animal>, so let's put it there: - { - package Animal; - + { package Animal; sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n" } - sub name { my $self = shift; $$self; } - sub named { my $class = shift; - my $name = shift; + my $name = shift; bless \$name, $class; } } - - { - package Horse; - - our @ISA = qw(Animal); - + { package Horse; + @ISA = qw(Animal); sub sound { "neigh" } } @@ -663,7 +615,7 @@ classname). Let's modify the C<name> method first to notice the change: sub name { my $either = shift; ref $either - ? $$either # it's an instance, return name + ? $$either # it's an instance, return name : "an unnamed $either"; # it's a class, return generic } @@ -673,8 +625,7 @@ instance or a class. Note that I've changed the first parameter holder to C<$either> to show that this is intended: my $talking = Horse->named("Mr. Ed"); - - print Horse->name, "\n"; # prints "an unnamed Horse\n" + print Horse->name, "\n"; # prints "an unnamed Horse\n" print $talking->name, "\n"; # prints "Mr Ed.\n" and now we'll fix C<speak> to use this: @@ -691,46 +642,34 @@ we're done! Let's train our animals to eat: - { - package Animal; + { package Animal; sub named { my $class = shift; - my $name = shift; + my $name = shift; bless \$name, $class; } - sub name { my $either = shift; ref $either - ? $$either # it's an instance, return name + ? $$either # it's an instance, return name : "an unnamed $either"; # it's a class, return generic } - sub speak { my $either = shift; print $either->name, " goes ", $either->sound, "\n"; } - sub eat { my $either = shift; - my $food = shift; + my $food = shift; print $either->name, " eats $food.\n"; } } - - { - package Horse; - - our @ISA = qw(Animal); - + { package Horse; + @ISA = qw(Animal); sub sound { "neigh" } } - - { - package Sheep; - - our @ISA = qw(Animal); - + { package Sheep; + @ISA = qw(Animal); sub sound { "baaaah" } } @@ -738,7 +677,6 @@ And now try it out: my $talking = Horse->named("Mr. Ed"); $talking->eat("hay"); - Sheep->eat("grass"); which prints: @@ -767,8 +705,7 @@ looks at the reference is changed accordingly. Let's make a sheep that has a name and a color: - my $data = { Name => "Evil", Color => "black" }; - my $bad = bless $data, Sheep; + my $bad = bless { Name => "Evil", Color => "black" }, Sheep; so C<< $bad->{Name} >> has C<Evil>, and C<< $bad->{Color} >> has C<black>. But we want to make C<< $bad->name >> access the name, and @@ -789,9 +726,8 @@ as well: ## in Animal sub named { my $class = shift; - my $name = shift; - my $self = { Name => $name, Color => $class->default_color }; - + my $name = shift; + my $self = { Name => $name, Color => $class->default_color }; bless $self, $class; } @@ -822,7 +758,6 @@ method or two to get and set the color. sub color { $_[0]->{Color} } - sub set_color { $_[0]->{Color} = $_[1]; } |