x625802392 发表于 2015-12-26 15:18:01

Perl 对象化编程的实现

缘由  最近反过头来看Perl,一方面是我的客户厂家用Perl开发了很多东西,另一方面在了解过程中,又复习了Perl语言,并且有了一些心得。记录下来,供大家参考。
  我在做一个小程序,就是解析一个文本文件,将其中的内容进行处理,并保存在另一个文件。


背景知识  1. Perl的对象化编程实现
  请参考阅读:
  O'Reilly - Advanced Perl Programming.pdf - 第7章
  2. 在Perl中如何使用引用
  http://www.iyunv.com/jh/25/504623.html
  3. Perl中如何读取文件
  Perl cookbook - 第7章
  4. Perl的正则表达式
  http://www.iyunv.com/jh/25/159388.html


具体实现  
  对象编程是为了解决长期依赖困扰的维护和扩展的工作。如果我们的代码只写一次,以后再也不需要改动,那么也许现代编程模型就不会演化。当然我们知道这是不可能的。世界唯一不变就是变化。
  Perl做为一种功能强大的脚本语言在各个方面都有运用(但没有在UI方面使用),但是由于脚本语言的特性,write once的标签一直伴随着它。大家普遍认为它是一种晦涩的并难以维护的程序语言。
  其实这方面,大家有一些误解。语言使用跟开发人员的水平和涵养有关系,即便在C#这种良好的高级对象语言的基础上,部分开发人员仍然可以写糟糕的难以读懂的语言结构来。因此,开发人员不仅仅是要学会在高级语言上使用对象编程,并更需要深刻理解对象概念,最终能将这种概念运用到不同的语言中来,使其语言结构,模块化,对象化。
  在我刚刚接触Perl的时候,我认为这种语言根本无法写出对象化的语言结构。因此,我对此有诸多抱怨。但随着学习的深入,Perl一样可以使用对象的概念来构件合适和清晰的语言结构。
  我把最后测试的代码先贴上来:

use filehandle::filehandler;
use filehandle::catchWorkerId;
print "\nTEST fildehander base class \n\n";
my $filehandler =filehandler->new("c:\\test2.ini");
print $filehandler->getDealedStrings();
print "\nTEST fildehander sub-class \n\n";
$filehandler = catchWorkerId->new("c:\\test2.ini");
print$filehandler->getDealedStrings();
$filehandler->exportToFile("C:\\test2_new.ini");  filehandler.PM和catchworkerId.PM是我们重要的两个Module(class)。fileHandler类是父类并完成了一个文件解析的基本动作:
  打开文件
  每行读取
  解析字符串并保存在类的数组变量里面
  导出到合适的文件中
  这样我们就可以只在子类里面完成需要变动的部分。请看子类代码catchworkId.PM


package catchWorkerId;
@ISA = qw(filehandler);
use strict;
use warnings;

sub convert
{
my ($self,$linetext) = @_;
my $pattern = "{9}[(]";
my @a;
if(@a=($linetext =~/$pattern/gio))
{
$a=~s/[(]//g;
return (1,$a);
}
return (0,"");
}
1;  
  




代码说明  子类代码只是完成一个方法convert,它的输入是一个$linetext 字符串标量,我们进行正则表达式的判断,如果满足匹配则返回true+替换后的$linetext,如果不满足就返回false+空字符串。
  如果在C#这类对象强类型语言中我们可以这样定义:


bool convert(string linetext, out string convetedlinetext)
{
//implemenet code
}  由于Perl是一种解释性非类型语言,因此我们需要变通的实现这一功能。 所以,如何在新的概念情况下,用旧有语言来实现特定的功能,就需要开发人员的创新能力,这些东西不会在教程上讲述,而需要开发人员自己的摸索。
  你看通过类的继承的方式,我们在子类只定义函数就完成我们预设目标。需要注意这一句:
  @ISA = qw(filehandler);
  它的意思是,引入filehandler.PM的函数,首先在catchWorkerId中查找调用函数,如果没有找到,会继续在filehandler.pm中查找。通过这种方式,我们完成了变相实现了类的继承。
  
  这里给出父类的实现:filehandler.PM


package filehandler;
use strict;
use warnings;
#new
sub new
{
my($class, $filename) = @_;
my $self ={
_filename =>$filename
};
my @ss;
$self->{_dealedStringArray}= \@ss;
return bless($self,$class);
}
#really open file
sub getDealedStrings
{
my($self) = @_;
open (FILEHANDLE,$self->{_filename})|| die("can't open file: $self->{_filename}");
#start to deal string line by line!
while(<FILEHANDLE>)
{
$self->handleLine($_);
}
close (FILEHANDLE);
return@{$self->{_dealedStringArray}} ;
}
#deal string line by line
sub handleLine
{
my ($self,$linetext) = @_;
my @result = $self->convert($linetext);
if($result==1)
{
$self->_addstring($result);
}

}
#You can write a override function in sub class
sub convert
{
my ($self,$old) = @_;
$old = "CONVERTED STRING:" .$old;
return (1,$old);
}
#add the dealed string into a array.
sub _addstring
{
my ($self,$linetext) = @_;
my @a =@{ $self->{_dealedStringArray}};
push(@a, $linetext."\n");
@{$self->{_dealedStringArray}} = @a;
}
#output converted file
sub exportToFile
{
my($self,$newFileName) = @_;
open FILEHANDLE ,">$newFileName" || die("can't create file : $newFileName");
for(my $i=0;$i<@{$self->{_dealedStringArray}};$i++)
{
print FILEHANDLE "${$self->{_dealedStringArray}}[$i]";
}
close FILEHANDLE;
}
1;  这里不在具体讲Perl 对象编程的概念,大家可以变参考背景知识里面推荐的O'Reilly - Advanced Perl Programming,边看本实例,一定会有所心得。
页: [1]
查看完整版本: Perl 对象化编程的实现