📄 ch4.htm
字号:
a function, an asterisk for any type, and a semicolon to indicate
that all other parameters are optional.
<P>
Now, let's look at the <TT><FONT FACE="Courier">lastMovingAverage</FONT></TT>
function declaration, which specifies two integers in the front
followed by an array. The way the arguments are used in the function
is to assign a value to each of the two scalars, <TT><FONT FACE="Courier">$count</FONT></TT>
and <TT><FONT FACE="Courier">$number</FONT></TT>, whereas everything
else is sent to the array. Look at the function <TT><FONT FACE="Courier">getMovingAverage()</FONT></TT>
to see how two arrays are passed in order to get the moving average
on a list of values.
<P>
The way to call the <TT><FONT FACE="Courier">getMovingAverage</FONT></TT>
function is shown in Listing 4.5.
<HR>
<BLOCKQUOTE>
<B>Listing 4.5. Using the moving average function.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl -w<BR>
2 <BR>
3 push(@Inc,'pwd');
<BR>
4 use Finance;<BR>
5 <BR>
6 @values = ( 12,22,23,24,21,23,24,23,23,21,29,27,26,28
);<BR>
7 @mv = (0);<BR>
8 $size = scalar(@values);<BR>
9 print "\n Values
to work with = { @values } \n";<BR>
10 print " Number of values = $size \n";<BR>
11 <BR>
12 # ----------------------------------------------------------------
<BR>
13 # Calculate the average of the above function<BR>
14 # ----------------------------------------------------------------
<BR>
15 $ave = Finance::getLastAverage(5,$size,@values);<BR>
16 print "\n Average of last 5 days = $ave \n";<BR>
17 <BR>
18 Finance::getMovingAve(5,$size,@values,@mv);<BR>
19 print "\n Moving Average with 5 days window = \n { @mv
} \n";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Here's the output from Listing 4.5:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Values to work with = { 12 22 23 24 21
23 24 23 23 21 29 27 26 28 }<BR>
Number of values = 14<BR>
<BR>
Average of last 5 days = 26.2<BR>
<BR>
Moving Average with 5 days window =<BR>
{ 0 0 0 0 0 19.4 21.8 22 22 21.4 23 23.8 24.2 25.2 }</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">getMovingAverage()</FONT></TT> function
takes two scalars and then two references to arrays as scalars.
Within the function, the two scalars to the arrays are dereferenced
for use as numeric arrays. The returned set of values is inserted
in the area passed in as the second reference. Had the input parameters
not been specified with <TT><FONT FACE="Courier">\@</FONT></TT>
for each referenced array, the <TT><FONT FACE="Courier">$movingAve</FONT></TT>
array reference would have been empty and would have caused errors
at runtime. In other words, the following declaration is not correct:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">sub getMovingAve($$@@)</FONT></TT>
</BLOCKQUOTE>
<P>
The resulting spew of error messages from a bad function prototype
is as follows:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Use of uninitialized value at Finance.pm
line 128.<BR>
Use of uninitialized value at Finance.pm line 128.<BR>
Use of uninitialized value at Finance.pm line 128.<BR>
Use of uninitialized value at Finance.pm line 128.<BR>
Use of uninitialized value at Finance.pm line 128.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
Use of uninitialized value at Finance.pm line 133.<BR>
Use of uninitialized value at Finance.pm line 135.<BR>
<BR>
Values to work with = { 12 22 23 24 21 23 24 23 23 21 29 27 26
28 }<BR>
Number of values = 14<BR>
<BR>
Average of last 5 days = 26.2<BR>
<BR>
Moving Average with 5 days window =<BR>
{ 0 }</FONT></TT>
</BLOCKQUOTE>
<P>
This is obviously not the correct output. Therefore, it's critical
that you pass by reference when sending more than one array.
<P>
Global variables for use within the package can also be declared.
Look at the following segment of code from the <TT><FONT FACE="Courier">Finance.pm</FONT></TT>
module to see what the default value of the <TT><FONT FACE="Courier">Interest</FONT></TT>
variable would be if nothing was specified in the input. (The
current module requires the interest to be passed in, but you
can change this.)
<P>
Here's a little snippet of code that can be added to the end of
the program shown in Listing 4.5 to add the ability to set interest
rates.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">20 local $defaultInterest = 5.0;<BR>
21 sub Finance::SetInterest($) {<BR>
22
my $rate = shift(@_);<BR>
23
$rate *= -1 if ($rate < 0); <BR>
24
$defaultInterest = $rate;<BR>
25
printf "\n \$defaultInterest = $rate";<BR>
26 }</FONT></TT>
</BLOCKQUOTE>
<P>
The local variable <TT><FONT FACE="Courier">$defaultInterest</FONT></TT>
is declared in line 20. The subroutine <TT><FONT FACE="Courier">SetInterest</FONT></TT>
to modify the rate is declared in lines 21 through 26. The <TT><FONT FACE="Courier">$rate</FONT></TT>
variable uses the values passed into the subroutine and simply
assigns a positive value for it. You can always add more error
checking if necessary.
<P>
To access the <TT><FONT FACE="Courier">defaultInterest</FONT></TT>
variable's value, you could define either a subroutine that returns
the value or refer to the value directly with a call to the following
in your application program:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$Finance::defaultInterest;</FONT></TT>
</BLOCKQUOTE>
<H3><A NAME="ReturnedValuesfromSubroutinesinaPa">Returned Values
from Subroutines in a Package</A></H3>
<P>
The variable holding the return value from the module function
is declared as <TT><FONT FACE="Courier">my variable</FONT></TT>.
The scope of this variable is within the curly braces of the function
only. When the called subroutine returns, the reference to <TT><FONT FACE="Courier">my
variable</FONT></TT> is returned. If the calling program uses
this returned reference somewhere, the link counter on the variable
is not zero; therefore, the storage area containing the returned
values is not freed to the memory pool. Thus, the function that
declares
<BLOCKQUOTE>
<TT><FONT FACE="Courier">my $pv</FONT></TT>
</BLOCKQUOTE>
<P>
and then later returns the value of <TT><FONT FACE="Courier">$pv</FONT></TT>
returns a reference to the value stored at that location. If the
calling routine performs a call like this one:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Finance::FVofAnnuity($monthly,$rate,$time);</FONT></TT>
</BLOCKQUOTE>
<P>
there is no variable specified here into which Perl stores the
returned reference; therefore, any returned value (or a list of
values) is destroyed. Instead, the call with the returned value
assigned to a local variable, such as this one:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$fv = Finance::FVofAnnuity($monthly,$rate,$time);</FONT></TT>
</BLOCKQUOTE>
<P>
maintains the variable with the value. Consider the example shown
in Listing 4.6, which manipulates values returned by functions.
<HR>
<BLOCKQUOTE>
<B>Listing 4.6. Sample usage of the </B><TT><B><FONT FACE="Courier">my</FONT></B></TT><B>
function.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl -w<BR>
2 <BR>
3 push(@Inc,'pwd');
<BR>
4 use Finance;<BR>
5 <BR>
6 $monthly = 400;<BR>
7 $rate = 0.2; #
i.e. 6 % APR<BR>
8 $time = 36; # in months<BR>
9 <BR>
10 print "\n# ------------------------------------------------";
<BR>
11 $fv = Finance::FVofAnnuity($monthly,$rate,$time);<BR>
12 printf "\n For a monthly %8.2f at a rate of %%%6.2f for
%d periods",<BR>
13
$monthly, $rate, $time;<BR>
14 printf "\n you get a future value of %8.2f ", $fv;
<BR>
15 <BR>
16 $fv *= 1.1; # allow 10 % gain in the house value.<BR>
17 <BR>
18 $mo = Finance::AnnuityOfFV($fv,$rate,$time);<BR>
19 <BR>
20 printf "\n To get 10 percent more at the end, i.e. %8.2f",$fv;
<BR>
21 printf "\n you need a monthly payment value of %8.2f",$mo,$fv;
<BR>
22 <BR>
23 print "\n# ------------------------------------------------
\n";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Here is sample input and output for this function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>testme<BR>
</B># ------------------------------------------------<BR>
For a monthly 400.00
at a rate of % 0.20 for 36 periods<BR>
you get a future value of 1415603.75<BR>
To get 10 percent more
at the end, i.e. 1557164.12<BR>
you need a monthly payment value of 440.00
<BR>
# ------------------------------------------------</FONT></TT>
</BLOCKQUOTE>
<H2><A NAME="MultipleInheritance"><FONT SIZE=5 COLOR=#FF0000>Multiple
Inheritance</FONT></A></H2>
<P>
Modules implement classes in a Perl program that uses the object-oriented
features of Perl. Included in object-oriented features is the
concept of <I>inheritance</I>. (You'll learn more on the object-oriented
features of Perl in <A HREF="ch5.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch5.htm" >Chapter 5</A>, "Object-Oriented
Programming in Perl.") Inheritance means the process with
which a module inherits the functions from its base classes. A
module that is nested within another module inherits its parent
modules' functions. So inheritance in Perl is accomplished with
the <TT><FONT FACE="Courier">::</FONT></TT> construct. Here's
the basic syntax:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SuperClass::NextSubClass:: ... ::ThisClass.</FONT></TT>
</BLOCKQUOTE>
<P>
The file for these is stored in <TT><FONT FACE="Courier">./SuperClass/NextSubClass/…</FONT></TT>.
Each double colon indicates a lower-level directory in which to
look for the module. Each module, in turn, declares itself as
a package with statements like the following:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">package SuperClass::NextSubClass;<BR>
package SuperClass::NextSubClass::EvenLower;</FONT></TT>
</BLOCKQUOTE>
<P>
For example, say that you really want to create a <TT><FONT FACE="Courier">Money</FONT></TT>
class with two subclasses, <TT><FONT FACE="Courier">Stocks</FONT></TT>
and <TT><FONT FACE="Courier">Finance</FONT></TT>. Here's how to
structure the hierarchy, assuming you are in the <TT><FONT FACE="Courier">/usr/lib/perl5</FONT></TT>
directory:
<OL>
<LI>Create a <TT><FONT FACE="Courier">Mone
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -