📄 ch5.htm
字号:
# Add code here.<BR>
#<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
For most purposes, Perl uses a simple reference-based garbage
collection system. The number of references to any given object
at the time of garbage collection has to be greater than zero,
or else the memory for that object is freed. When your program
exits, an exhaustive search-and-destroy function in Perl does
the garbage collection. Everything in the process is summarily
deleted. In UNIX or UNIX-like systems, this may seem like a waste,
but it is actually quite necessary in embedded systems or in a
multithreaded environment.
<H2><A NAME="Inheritance"><FONT SIZE=5 COLOR=#FF0000>Inheritance</FONT></A>
</H2>
<P>
Methods in classes are inherited with the use of the paths in
the <TT><FONT FACE="Courier">@ISA</FONT></TT> array. Variables
have to be inherited and set up explicitly for inheritance. Let's
say you define a new class called <TT><FONT FACE="Courier">Bean.pm</FONT></TT>
to include some of the functionality that another class, <TT><FONT FACE="Courier">Coffee.pm</FONT></TT>,
will inherit.
<P>
The example in this section demonstrates how to inherit instance
variables from one class (also referred to as a <I>superclass</I>
or <I>base class</I>). The steps in inheritance require calling
the superclass's constructor and adding one's own instance variables
to the new object.
<P>
In this example, the <TT><FONT FACE="Courier">Coffee</FONT></TT>
class is the class that inherits values from the base class <TT><FONT FACE="Courier">Bean</FONT></TT>.
The two files are called <TT><FONT FACE="Courier">Coffee.pm</FONT></TT>
and <TT><FONT FACE="Courier">Bean.pm</FONT></TT>, respectively.
The code for <TT><FONT FACE="Courier">Bean.pm</FONT></TT> is shown
in Listing 5.12.
<HR>
<BLOCKQUOTE>
<B>Listing 5.12. The </B><TT><B><FONT FACE="Courier">Bean.pm</FONT></B></TT><B>
file.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 package Bean;<BR>
2 require Exporter;<BR>
3 <BR>
4 @ISA = qw(Exporter);<BR>
5 @EXPORT = qw(setBeanType);
<BR>
6 <BR>
7 sub new {<BR>
8 my $type = shift;<BR>
9
my $this = {};<BR>
10 $this->{'Bean'} = 'Colombian';<BR>
11 bless $this, $type;<BR>
12 return $this;<BR>
13 }<BR>
14 <BR>
15 #<BR>
16 # This subroutine sets the<BR>
17 sub setBeanType{<BR>
18 my ($class, $name) = @_;
<BR>
19 $class->{'Bean'} = $name;<BR>
20 print "Set bean to $name \n";
<BR>
21 }<BR>
22 1;</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
In this listing, the <TT><FONT FACE="Courier">$this</FONT></TT>
variable sets a value in the anonymous hash for the <TT><FONT FACE="Courier">'Bean'</FONT></TT>
class to be <TT><FONT FACE="Courier">'Colombian'</FONT></TT>.
The <TT><FONT FACE="Courier">setBeanType</FONT></TT> function
method is also declared so that the item referred to by the word
<TT><FONT FACE="Courier">'Bean' </FONT></TT>is set for any class
that is sent in as an argument. Therefore, you can use this <TT><FONT FACE="Courier">setBeanType</FONT></TT>
function in other classes to set the value of any member whose
name is <TT><FONT FACE="Courier">'Bean'</FONT></TT>.
<P>
The subroutine for resetting the value of <TT><FONT FACE="Courier">'Bean'</FONT></TT>
uses the <TT><FONT FACE="Courier">$class</FONT></TT> reference
to get to the anonymous hash for the object. Remember that it
is a reference to this anonymous hash that created the reference
in the first place with the <TT><FONT FACE="Courier">new()</FONT></TT>
function.
<P>
The values in the <TT><FONT FACE="Courier">Bean</FONT></TT> class
are inherited by the <TT><FONT FACE="Courier">Coffee</FONT></TT>
class. The <TT><FONT FACE="Courier">Coffee.pm</FONT></TT> file
is shown in Listing 5.13.
<HR>
<BLOCKQUOTE>
<B>Listing 5.13. Using inheritance.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #<BR>
2 # The Coffee.pm file to illustrate
inheritance.<BR>
3 #
<BR>
4 package Coffee;<BR>
5 require
Exporter;<BR>
6 require Bean;<BR>
7 @ISA
= qw(Exporter, Bean);<BR>
8 @EXPORT = qw(setImports, declareMain,
closeMain);<BR>
9
#<BR>
10 # set item<BR>
11 #<BR>
12 sub setCoffeeType{<BR>
13 my ($class,$name)
= @_;<BR>
14 $class->{'Coffee'}
= $name;<BR>
15 print
"Set coffee type to $name \n";<BR>
16 }<BR>
17 #<BR>
18 # constructor<BR>
19 #<BR>
20 sub new {<BR>
21 my $type =
shift;<BR>
22 my $this =
Bean->new(); ##### <-- LOOK HERE!!!
####<BR>
23 $this->{'Coffee'}
= 'Instant'; # unless told otherwise<BR>
24 bless
$this, $type;<BR>
25 return
$this;<BR>
26 }<BR>
27 1;</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Note the use of the <TT><FONT FACE="Courier">require Bean;</FONT></TT>
statement at line 6. (<A HREF="ch4.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch4.htm" >See Chapter 4</A>, "Introduction
to Perl Modules," in the section titled "Using Perl
Modules" for the reasons why the <TT><FONT FACE="Courier">require</FONT></TT>
statement is used instead of the <TT><FONT FACE="Courier">use</FONT></TT>
statement.) This line forces the inclusion of the <TT><FONT FACE="Courier">Bean.pm</FONT></TT>
file and all its related functions without importing the functions
until compile time. Lines 12 through 16 define a subroutine to
use when resetting the value of the local variable in <TT><FONT FACE="Courier">$class->{'Coffee'}</FONT></TT>.
<P>
Look at the <TT><FONT FACE="Courier">new()</FONT></TT> constructor
for the <TT><FONT FACE="Courier">Coffee</FONT></TT> class. The
<TT><FONT FACE="Courier">$this</FONT></TT> reference points to
the anonymous hash returned by <TT><FONT FACE="Courier">Bean.pm</FONT></TT>,
not a hash created locally. In other words, the following statement
creates an entirely different hash that has nothing to do with
the hash created in the <TT><FONT FACE="Courier">Bean.pm</FONT></TT>
constructor.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">my $this = {}; # This is not the way
to do it for inheritance.<BR>
my $this = $theSuperClass->new(); # this is the way.</FONT></TT>
</BLOCKQUOTE>
<P>
Listing 5.14 illustrates how to call these functions.
<HR>
<BLOCKQUOTE>
<B>Listing 5.14. Using inheritance.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 push (@Inc,'pwd');<BR>
3 use Coffee;<BR>
4 $cup = new Coffee;<BR>
5 print "\n --------------------
Initial values ------------ \n";<BR>
6 print "Coffee: $cup->{'Coffee'} \n";<BR>
7 print "Bean:
$cup->{'Bean'} \n";<BR>
8 print "\n -------------------- Change Bean Type ----------
\n";<BR>
9 $cup->setBeanType('Mixed');
<BR>
10 print "Bean Type is now $cup->{'Bean'} \n";<BR>
11 print "\n ------------------ Change Coffee Type ----------
\n";<BR>
12 $cup->setCoffeeType('Instant');<BR>
13 print "Type of coffee: $cup->{'Coffee'} \n";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The initial values for the <TT><FONT FACE="Courier">'Bean'</FONT></TT>
and <TT><FONT FACE="Courier">'Coffee'</FONT></TT> indexes in the
anonymous hash for the object are printed first. The member functions
are called to set the values to different names and are printed
out.
<P>
Here is the output of the script:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">-------------------- Initial values ------------
<BR>
Coffee: Instant<BR>
Bean: Colombian<BR>
<BR>
-------------------- Change Bean Type ----------<BR>
Set bean to Mixed<BR>
Bean Type is now Mixed<BR>
<BR>
------------------ Change Coffee Type ----------<BR>
Set coffee type to Instant<BR>
Type of coffee: Instant</FONT></TT>
</BLOCKQUOTE>
<P>
Methods can have several types of arguments. It's how you process
the arguments that counts. For example, you can add the method
shown in Listing 5.15 to the <TT><FONT FACE="Courier">Coffee.pm</FONT></TT>
module.
<HR>
<BLOCKQUOTE>
<B>Listing 5.15. Variable-length lists of parameters.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">1 sub makeCup {<BR>
2 my ($class, $cream, $sugar,
$dope) = @_;<BR>
3 print "\n==================================
\n";<BR>
4 print "Making a cup
\n";<BR>
5 print "Add cream \n"
if ($cream);<BR>
6 print "Add $sugar sugar
cubes\n" if ($sugar);<BR>
7 print "Making some really
addictive coffee ;-) \n" if ($dope);<BR>
8 print "==================================
\n";<BR>
9 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
This function takes three arguments, but it processes them only
if it sees them. To test this functionality, consider the Perl
code shown in Listing 5.16.
<HR>
<BLOCKQUOTE>
<B>Listing 5.16. Testing variable length lists.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl
<BR>
2 push (@Inc,'pwd');<BR>
3 use
Coffee;<BR>
4 $cup = new Coffee;<BR>
5 #
<BR>
6 # With no parameters
<BR>
7 #
<BR>
8 print "\n Calling with
no parameters: \n";<BR>
9 $cup->makeCup;
<BR>
10 #<BR>
11 # With one parameter<BR>
12 #<BR>
13 print "\n Calling with
one parameter: \n";<BR>
14 $cup->makeCup('1');<BR>
15 #<BR>
16 # With two parameters<BR>
17 #<BR>
18 print "\n Calling with
two parameters: \n";<BR>
19 $cup->makeCup(1,'2');<BR>
20 #<BR>
21 # With all three parameters
<BR>
22 #<BR>
23 print "\n Calling with
three parameters: \n";<BR>
24 $cup->makeCup('1',3,'1');</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Line 9 calls the function with no parameters. In Line 14, the
call is with one parameter. The parameters are passed either as
strings or integers-something this particular method does not
care about (see lines 19 and 24). However, some methods you write
in the future may require this distinction.
<P>
Here's the output from this program:
<BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -