📄 ch6.htm
字号:
51 my
$self = shift;<BR>
52 confess
"wrong type" unless ref $self;<BR>
53 my
$value = shift;<BR>
54 confess
"Hey dude! We are making this readonly!\n";<BR>
55 return
$value;<BR>
56 }
<BR>
57<BR>
58 #<BR>
59 # DESTROY this<BR>
60 # This method will be triggered when the tied variable needs
to be<BR>
61 # destructed. This method can be just empty for most classes
since<BR>
62 # Perl's garbage collection will.<BR>
63 #<BR>
64<BR>
65 sub DESTROY {<BR>
66 my
$self = shift;<BR>
67 confess
"wrong type" unless ref $self;<BR>
68 print
"\nKnot:: unknotted!\n";<BR>
69 }
<BR>
70<BR>
71 #<BR>
72 # The obligatory ending true statement.<BR>
73 #<BR>
74 1;</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
<TT><FONT FACE="Courier">Knot.pm</FONT></TT> defines the package
in line 10 and imports the <TT><FONT FACE="Courier">Carp</FONT></TT>
and <TT><FONT FACE="Courier">strict</FONT></TT> packages in lines
11 and 12, respectively. Line 74 terminates the module.
<P>
Lines 19 through 26 define the <TT><FONT FACE="Courier">TIESCALAR</FONT></TT>
function. The <TT><FONT FACE="Courier">TIESCALAR</FONT></TT> function
behaves a lot like the constructor of an object in Perl. It creates
an associative array and returns a reference to this array after
a call to the <TT><FONT FACE="Courier">bless()</FONT></TT> function.
(<A HREF="ch5.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch5.htm" >See Chapter 5</A>, "Object-Oriented Programming
in Perl," for more information on <TT><FONT FACE="Courier">bless</FONT></TT>-ing
objects.)
<P>
The <TT><FONT FACE="Courier">FETch</FONT></TT> method starts at
line 35. The <TT><FONT FACE="Courier">FETch</FONT></TT> method
is called every time the tied variable is read from. The only
argument to the <TT><FONT FACE="Courier">FETch</FONT></TT> method
is a reference to the object itself. At line 37, the class type
is confirmed, although it's not absolutely necessary to do this.
Lines 39 through 41 return the current date and time for the value
of the tied variable.
<P>
The <TT><FONT FACE="Courier">STORE</FONT></TT> method is defined
from line 50 through 56. In this case, we do not let values of
the arguments that are passed in be assigned to anything because
we want to make this value a read-only variable. You can easily
modify this function to take some other action than what's shown
in this example. The <TT><FONT FACE="Courier">FETch</FONT></TT>
method takes only two arguments: a reference to itself and a value
that is being assigned. The <TT><FONT FACE="Courier">confess()</FONT></TT>
call is from within the <TT><FONT FACE="Courier">Carp</FONT></TT>
module.
<P>
The <TT><FONT FACE="Courier">DESTROY</FONT></TT> method is called
when the tied variable is destroyed. Normally, this function is
empty. For this example, there is a <TT><FONT FACE="Courier">print</FONT></TT>
statement to show where the <TT><FONT FACE="Courier">DESTROY</FONT></TT>
function is called.
<H2><A NAME="TyingtoanArray"><FONT SIZE=5 COLOR=#FF0000>Tying
to an Array</FONT></A></H2>
<P>
An array variable can be tied to a class in the same manner as
a scalar can be tied to a class. The real difference is that the
input parameters to the methods now need an index used to address
a value in array. A class implementing an ordinary array must
have these methods:
<UL>
<LI><TT><FONT FACE="Courier">TIEARRAY classname, LIST</FONT></TT>
<LI><TT><FONT FACE="Courier">FETch this, key</FONT></TT>
<LI><TT><FONT FACE="Courier">STORE this, key, value</FONT></TT>
<LI><TT><FONT FACE="Courier">DESTROY this</FONT></TT>
</UL>
<P>
The <TT><FONT FACE="Courier">FETch</FONT></TT>, <TT><FONT FACE="Courier">DESTROY</FONT></TT>,
and <TT><FONT FACE="Courier">STORE</FONT></TT> methods have the
same names as those for scalars. However, the name of the constructor
is different-it's called <TT><FONT FACE="Courier">TIEARRAY</FONT></TT>.
Let's define a new array type called <TT><FONT FACE="Courier">Cuboid</FONT></TT>,
which has its first five indexes provide special functions. The
first three indexes are written to as the height, width, and depth
of a cuboid. The next two indexes contain the volume and surface
area of the cuboid and are made read-only. The rest of the array
can be made into a bounded array to allow a user to store his
or her own values. As soon as a value is stored in the <TT><FONT FACE="Courier">Cuboid</FONT></TT>
array, the values of items at index <TT><FONT FACE="Courier">3</FONT></TT>
and <TT><FONT FACE="Courier">4</FONT></TT> are recalculated to
provide the latest volume and surface area of a cuboid.
<P>
Listing 6.3 illustrates how to use this array.
<HR>
<BLOCKQUOTE>
<B>Listing 6.3. Using the </B><TT><B><FONT FACE="Courier">Cuboid.pm</FONT></B></TT><B>
module.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2<BR>
3 push(@Inc,".");
<BR>
4 use Cuboid;<BR>
5<BR>
6 tie @myCube, 'Cuboid', 3;<BR>
7<BR>
8 $myCube[0] = 2;<BR>
9 $myCube[1] = 3;<BR>
10 $myCube[2] = 4;<BR>
11<BR>
12 for ($i=0; $i < 5; $i++) {<BR>
13 print " myCube[$i] = $myCube[$i]
\n";<BR>
14 }<BR>
15</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Here is the output of this code.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">array will be 8 elements long<BR>
[STORE 2 at 0]<BR>
[STORE 3 at 1]<BR>
[STORE 4 at 2]<BR>
myCube[0] = 2<BR>
myCube[1] = 3<BR>
myCube[2] = 4<BR>
myCube[3] = 24<BR>
myCube[4] = 52</FONT></TT>
</BLOCKQUOTE>
<P>
Now let's examine the <TT><FONT FACE="Courier">Cuboid.pm</FONT></TT>
module, which is presented in Listing 6.4.
<HR>
<BLOCKQUOTE>
<B>Listing 6.4. The </B><TT><B><FONT FACE="Courier">Cuboid.pm</FONT></B></TT><B>
module.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 # ------------------------------------------------------------
<BR>
2 package Cuboid;<BR>
3 use Carp;<BR>
4 use strict;<BR>
5<BR>
6 #<BR>
7 # The constructor
for this class.<BR>
8 # ------------------------------------------------------------
<BR>
9 # Array[0] = ht;
read write<BR>
10 # Array[1] = wd;
read write<BR>
11 # Array[2] = dp;
read write<BR>
12 # Array[3] = volume; read
only<BR>
13 # Array[4] = surfaceArea; read only<BR>
14 # Array[5...maxsize] = read/write values for the user;<BR>
15 # ------------------------------------------------------------
<BR>
16<BR>
17 my $SACRED = 5;<BR>
18<BR>
19 sub TIEARRAY {<BR>
20<BR>
21 my $class = shift;<BR>
22 my $maxsize = shift;<BR>
23<BR>
24 #<BR>
25 # Bailout if the array is not tied
correctly.<BR>
26 #<BR>
27 confess
"usage: tie(\@ary, 'Cuboid', maxsize)"<BR>
28 if
@_ || $maxsize =~ /\D/;<BR>
29 $maxsize
+= $SACRED;<BR>
30 print
"array will be $maxsize elements long\n";<BR>
31 return
bless {<BR>
32 MAXSIZE
=> $maxsize,<BR>
33 ARRAY
=> [0,0,0,0,0],<BR>
34 },
$class;<BR>
35 }
<BR>
36<BR>
37 # FETch this, index<BR>
38 # This method will be triggered every time an individual element
the tied<BR>
39 # array is accessed (read). It takes one argument beyond its
self<BR>
40 # reference: the index whose value we're trying to fetch.<BR>
41 #<BR>
42 sub FETch {<BR>
43 my($self,$ndx)
= @_;<BR>
44 if
($ndx > $self->{MAXSIZE}) {<BR>
45 confess
"Error Out of Bounds: $ndx > $self->{MAXSIZE}";
<BR>
46 }
<BR>
47 return
$self->{ARRAY}[$ndx];<BR>
48 }
<BR>
49<BR>
50 # STORE this, index, value<BR>
51 # This method will be called whenever an element in the tied
array<BR>
52 # is written to. It takes three arguments: a reference to itself,
<BR>
53 # the index to store stuff at, and the value to store at the
index.<BR>
54 #<BR>
55 # The items at [3] and [4] are not allowed to be written to.
<BR>
56 #<BR>
57 sub STORE {<BR>
58 my($self,
$ndx, $value) = @_;<BR>
59 print
"[STORE $value at $ndx]\n";<BR>
60 if
($ndx > $self->{MAXSIZE} ) {<BR>
61 confess
"Error Out Of Bounds: $ndx > $self->{MAXSIZE}";
<BR>
62 }
<BR>
63 if (($ndx ==
3) || ( $ndx == 4)) {<BR>
64 confess
"Cannot store in read only area: $ndx";<BR>
65 }
<BR>
66 $self->{ARRAY}[$ndx]
= $value;<BR>
67
$self->{ARRAY}[3] =<BR>
68 ($self->{ARRAY}[0]
* $self->{ARRAY}[1] * $self->{ARRAY}[2]) ;<BR>
69
$self->{ARRAY}[4] =<BR>
70 ($self->{ARRAY}[0]
* $self->{ARRAY}[1]) +<BR>
71 ($self->{ARRAY}[1]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -