⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perl13.htm

📁 perl快速入门。由浅入深
💻 HTM
📖 第 1 页 / 共 3 页
字号:
11 #<br>
12 sub setCoffeeType{<br>
13 &nbsp;    my ($class,$name) =  @_;<br>
14 &nbsp;    $class->{'Coffee'} = $name;<br>
15 &nbsp;    print "Set coffee type to $name \n";<br>
16 &nbsp;    }<br>
17  #<br>
18  #  constructor<br>
19  #<br>
20  sub new {<br>
21 &nbsp;     my $type  = shift;<br>
22 &nbsp;      my $this  = Bean->new();     ##### <- LOOK HERE!!! ####<br>
23 &nbsp;     $this->{'Coffee'} = 'Instant';  # unless told otherwise<br>
24 &nbsp;     bless $this, $type;<br>
25 &nbsp;     return $this;<br>
26 &nbsp;     }<br>
27  1;
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;第6行的require Bean;语句包含了Bean.pm文件和所有相关函数,方法setCoffeeType()用于设置局域变量$class->{'Coffee'}的值。在构造函数new()中,$this指向Bean.pm返回的匿名哈希表的指针,而不是在本地创建一个,下面两个语句分别为创建不同的哈希表从而与Bean.pm构造函数创建的哈希表无关的情况和继承的情况:<br>
&nbsp;&nbsp;&nbsp;&nbsp;my $this = {}; #非继承<br>
&nbsp;&nbsp;&nbsp;&nbsp;my $this = $theSuperClass->new(); #继承<br>
&nbsp;&nbsp;&nbsp;&nbsp;下面代码演示如何调用继承的方法:<br>
<blockquote>
1&nbsp;   #!/usr/bin/perl<br>
2&nbsp;   push (@INC,'pwd');<br>
3&nbsp;   use Coffee;<br>
4&nbsp;   $cup = new Coffee;<br>
5&nbsp;   print "\n -------------------- Initial values ------------ \n";<br>
6&nbsp;   print "Coffee: $cup->{'Coffee'} \n";<br>
7&nbsp;   print "Bean: $cup->{'Bean'} \n";<br>
8&nbsp;   print "\n -------------------- Change Bean Type ---------- \n";<br>
9&nbsp;   $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";
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;该代码的结果输出如下:<br>
<blockquote>
 -------------------- Initial values ------------<br>
 Coffee: Instant<br>
 Bean: Colombian<br>
 -------------------- Change Bean Type ----------<br>
 Set bean to Mixed<br>
 Bean Type is now Mixed <br>
 ------------------ Change Coffee Type ----------<br>
 Set coffee type to Instant<br>
 Type of coffee: Instant
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;上述代码中,先输出对象创建时哈希表中索引为'Bean'和'Coffee'的值,然后调用各成员函数改变值后再输出。<br>
&nbsp;&nbsp;&nbsp;&nbsp;方法可以有多个参数,现在向Coffee.pm模块增加函数makeCup(),代码如下:<br>
<blockquote>
sub makeCup {<br>
 &nbsp;   my ($class, $cream, $sugar, $dope) = @_;<br>
 &nbsp;   print "\n================================== \n";    <br>
 &nbsp;   print "Making a cup \n";<br>
 &nbsp;   print "Add cream \n" if ($cream);<br>
 &nbsp;   print "Add $sugar sugar cubes\n" if ($sugar);<br>
 &nbsp;   print "Making some really addictive coffee ;-) \n" if ($dope);<br>
 &nbsp;   print "================================== \n";<br>
}
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;此函数可有三个参数,不同数目、值的参数产生不同的结果,例如:<br>
<blockquote>
1&nbsp;   #!/usr/bin/perl<br>
2&nbsp;   push (@INC,'pwd');<br>
3&nbsp;   use Coffee;<br>
4&nbsp;   $cup = new Coffee;<br>
5&nbsp;   #<br>
6&nbsp;   #  With no parameters<br>
7&nbsp;   #<br>
8&nbsp;   print "\n Calling  with no parameters: \n";<br>
9&nbsp;   $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');
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;其结果输出如下:<br>
<blockquote>
 Calling  with no parameters:<br>
==================================<br>
Making a cup<br>
==================================<br>
 Calling  with one parameter:<br>
==================================<br>
Making a cup<br>
Add cream<br>
==================================<br>
 Calling  with two parameters:<br>
==================================<br>
Making a cup<br>
Add cream<br>
Add 2 sugar cubes<br>
==================================<br>
 Calling  with three parameters:<br>
==================================<br>
Making a cup<br>
Add cream<br>
Add 3 sugar cubes<br>
Making some really addictive coffee ;-)<br>
==================================
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;在此例中,函数makeCup()的参数既可为字符串也可为整数,处理结果相同,你也可以把这两种类型的数据处理区分开。在对参数的处理中,可以设置缺省的值,也可以根据实际输入参数值的个数给予不同处理。<br>
<a name="11">十一、子类方法的重载</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;继承的好处在于可以获得基类输出的方法的功能,而有时需要对基类的方法重载以获得更具体或不同的功能。下面在Bean.pm类中加入方法printType(),代码如下:<br>
<blockquote>
sub printType {<br>
 &nbsp;   my $class =  shift @_;<br>
 &nbsp;   print "The type of Bean is $class->{'Bean'} \n";<br>
}
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;然后更新其@EXPORT数组来输出:<br>
&nbsp;&nbsp;&nbsp;&nbsp;@EXPORT = qw ( setBeanType , printType );<br>
&nbsp;&nbsp;&nbsp;&nbsp;现在来调用函数printType(),有三种调用方法:<br>
<blockquote>
$cup->Coffee::printType();<br>
$cup->printType();<br>
$cup->Bean::printType();
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;输出分别如下:<br>
<blockquote>
The type of Bean is Mixed<br>
The type of Bean is Mixed<br>
The type of Bean is Mixed
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;为什么都一样呢?因为在子类中没有定义函数printType(),所以实际均调用了基类中的方法。如果想使子类有其自己的printType()函数,必须在Coffee.pm类中加以定义:<br>
<blockquote>
#<br>
# This routine prints the type of $class->{'Coffee'}<br>
#<br>
sub printType {<br>
 &nbsp;   my $class =  shift @_;<br>
 &nbsp;   print "The type of Coffee is $class->{'Coffee'} \n";<br>
}
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;然后更新其@EXPORT数组:<br>
&nbsp;&nbsp;&nbsp;&nbsp;@EXPORT = qw(setImports, declareMain, closeMain, printType);<br>
&nbsp;&nbsp;&nbsp;&nbsp;现在输出结果变成了:<br>
<blockquote>
The type of Coffee is Instant<br>
The type of Coffee is Instant<br>
The type of Bean is Mixed
</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;现在只有当给定了Bean::时才调用基类的方法,否则直接调用子类的方法。<br>
&nbsp;&nbsp;&nbsp;&nbsp;那么如果不知道基类名该如何调用基类方法呢?方法是使用伪类保留字SUPER::。在类方法内使用语法如:$this->SUPER::function(...argument list...); ,它将从@ISA列表中寻找。刚才的语句用SUPER::替换Bean::可以写为$cup->SUPER::printType(); ,其结果输出相同,为:<br>
<blockquote>The type of Bean is Mixed</blockquote>
 十二、Perl类和对象的一些注释<br>
&nbsp;&nbsp;&nbsp;&nbsp;OOP的最大好处就是代码重用。OOP用数据封装来隐藏一些复杂的代码,Perl的包和模块通过my函数提供数据封装功能,但是Perl并不保证子类一定不会直接访问基类的变量,这确实减少了数据封装的好处,虽然这种动作是可以做到的,但却是个很坏的编程风格。<br>
注意:<blockquote>1、一定要通过方法来访问类变量。<br>2、一定不要从模块外部直接访问类变量。</blockquote>
&nbsp;&nbsp;&nbsp;&nbsp;当编写包时,应该保证方法所需的条件已具备或通过参数传递给它。在包内部,应保证对全局变量的访问只用通过方法传递的引用来访问。对于方法要使用的静态或全局数据,应该在基类中用local()来定义,子类通过调用基类来获取。有时,子类可能需要改变这种数据,这时,基类可能就不知道怎样去寻找新的数据,因此,这时最好定义对该数据的引用,子类和基类都通过引用来改变该数据。<br>
&nbsp;&nbsp;&nbsp;&nbsp;最后,你将看到如下方式来使用对象和类:<br>
&nbsp;&nbsp;&nbsp;&nbsp;use coffee::Bean;<br>
&nbsp;&nbsp;&nbsp;&nbsp;这句语句的含义是“在@INC数组所有目录的Coffee子目录来寻找Bean.pm”。如果把Bean.pm移到./Coffee目录,上面的例子将用这一use语句来工作。这样的好处是有条理地组织类的代码。再如,下面的语句:<br>
&nbsp;&nbsp;&nbsp;&nbsp;use Another::Sub::Menu;<br>
&nbsp;&nbsp;&nbsp;&nbsp;意味着如下子目录树:<br>
&nbsp;&nbsp;&nbsp;&nbsp;./Another/Sub/Menu.pm<br>


<p align="center"><a href="perl12.htm">上一章</a> <a href="perl14.htm">下一章</a> <a href="index.htm">目录</a></p>

  	  </td>
      </tr>        
      </table>
    </td>
  </tr>
</table>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -