浅谈Perl的类、包、模块与面对对象编程

http://blog.chinaunix.net/uid-27464093-id-3308003.html

Perl面向对象

 Perl面向对象学习例子实例代码教程 - 在我们了解perl的面向对象的概念开始之前,让我们了解引用和匿名数组和哈希表。
  在我们了解perl的面向对象的概念开始之前,让我们了解引用和匿名数组和哈希表。
 引用
  引用是完全像名称所暗示的一样,给另一个对象的引用或指针。
  有两种类型的引用:符号和硬引用。
  一个符号参考,使您能够引用一个变量的名称,使用另一个变量值。 例如,如果变量$foo的包含字符串“bar”,符号引用$foo的关联变量$bar。
  一个硬引用是指在数据结构中包含的实际数据。
 创建硬引用
  一元反斜线运算符用于创建一个命名的变量或子程序,例如:
 $foo = ‘Bill‘;
$fooref = \$foo;
  现在$fooref变量一个硬引用$foo的变量。你可以做同样的与其他变量:
 $array = \@ARGV;
$hash = \%ENV;
$glob = \*STDOUT;
  要创建一个子程序:
 sub foo { print "foo" };
$foosub = \&foo;
 匿名数组
  当你直接创建一个引用到一个数组 - 也就是说,没有形成中间指定数组 - 您正在创建一个匿名数组。
  创建一个匿名数组是很容易的:
 $array = [ ‘Bill‘, ‘Ben, ‘Mary‘ ];
  这一行分配一个数组,由封闭的方括号中,而不是正常的括号表示,标量$array。赋值的右侧上的值,使该阵列和左侧包含此阵列的参考。
  您可以创建更复杂的结构,通过嵌套数组:
 @arrayarray = ( 1, 2, [1, 2, 3]);
  @array数组包含三个元素,一个匿名的三个元素的数组的第三个元素是一个引用。
 匿名散列
  匿名哈希,你也很容易创建需要使用大括号方括号:
 $hash = { ‘Man‘ => ‘Bill‘,
  ‘Woman‘ => ‘Mary,
  ‘Dog‘ => ‘Ben‘
};
 解除引用
  解引用一个参考的最直接的方法是在前面加上相应的数据类型的字符(标量使用$,阵列使用@,哈希使用%,子程序用&)是你期待在前面的标量量变量包含的引用。
 $array = \@ARGV;     # Create reference to array
$hash = \%ENV;       # Create reference to hash
$glob = \*STDOUT;    # Create reference to typeglob
$foosub = \&foo;     # Create reference to subroutine
#by www.yiibai.com
push (@$array, "From humans");
$$array[0] = ‘Hello‘
$$hash{‘Hello‘} = ‘World‘;
&$foosub;
print $glob "Hello World!\n";
对象基础
  主要有三种,解释的Perl如何处理对象的角度来看。 该使用条款是对象,类和方法。
  在Perl中,对象仅仅是一个参考的数据类型,它知道它属于什么类。对象存储在一个标量变量作为参考。因为一个标量只包含一个对象的引用,同样的标量可以容纳不同的对象,不同的类中。
  在Perl中类是一个包,其中包含需要相应的方法来创建和操作对象。
  在Perl中一个子程序,程序包定义的方法。该方法的第一个参数是一个对象引用或包名称,取决于该方法是否影响当前对象或类。
 Perl提供了bless()函数,用于返回一个引用,并成为一个对象。
定义一个类
  定义一个类很简单。在Perl中类是对应于一个包。要创建一个类,我们先建立一个包。包是一个独立的单元,用户定义的变量和子程序,它可以被重新使用一遍又一遍。他们提供了一个单独的命名空间内保持一个Perl程序,子程序和变量以免与其他包中的冲突。
  要声明一个类名为Person,我们做:
 package Person;
  包定义的范围延伸到该文件的末尾,或直到遇到另一个package关键字。
创建和使用对象
  要创建一个类的实例(对象),我们需要一个对象的构造函数。此构造函数是一个在包中定义的方法。大多数程序员来命名这种新对象的构造方法,但在Perl中,可以使用任何名称。
  在Perl中的对象,我们可以使用任何类型的Perl变量。大多数Perl程序员选择使用数组或哈希表的引用。
  让我们来创建我们的构造函数使用一个Perl的哈希参考我们的Person类;
  当创建一个对象,你需要提供一个构造函数。这是一个子程序,它返回一个对象引用在一个包内。blessing包的类创建的对象引用。例如:
 package Person;
sub new
{
  my $class = shift;
  my $self = {
  _firstName => shift,
  _lastName  => shift,
  _ssn       => shift,
  };
  # Print all the values just for clarification.
  #by www.yiibai.com
  print "First Name is $self->{_firstName}\n";
  print "Last Name is $self->{_lastName}\n";
  print "SSN is $self->{_ssn}\n";
  bless $self, $class;
  return $self;
}
  每类方法通过类名作为第一个参数。 因此,在上面的例子中的类名是“Person”。你可以试试这个打印$class的值。下一步将剩下的参数传递的方法。
 $object = new Person( "Mohammad", "Saleem", 23234345);
  如果不希望任何类变量分配任何值,可以使用简单的哈希在构造函数。例如
 package Person;
sub new
{
  my $class = shift;
  my $self = {};
  bless $self, $class;
  return $self;
}
定义方法
  其它面向对象语言的概念,如:数据的安全性,以防止程序员等提供直接改变一个对象的数据访问方法来修改对象数据。 Perl没有私有变量,但我们仍然可以使用辅助函数的方法,让程序员不要乱用对象内部结构的概念。
  让我们来定义一个辅助方法来获得人的名字:
 sub getFirstName {
  return $self->{_firstName};
}
  另一种辅助函数来设置人的名字:
 sub setFirstName {
  my ( $self, $firstName ) = @_;
  $self->{_firstName} = $firstName if defined($firstName);
  return $self->{_firstName};
}
  让我们看看到完整的例子:保持Person  包和辅助功能Person.pm文件。
 #!/usr/bin/perl
package Person;
sub new
{
  my $class = shift;
  my $self = {
  _firstName => shift,
  _lastName  => shift,
  _ssn       => shift,
  };
  # Print all the values just for clarification.
  print "First Name is $self->{_firstName}\n";
  print "Last Name is $self->{_lastName}\n";
  print "SSN is $self->{_ssn}\n";
  bless $self, $class;
  return $self;
}
sub setFirstName {
  my ( $self, $firstName ) = @_;
  $self->{_firstName} = $firstName if defined($firstName);
  return $self->{_firstName};
}
#by www.yiibai.com
sub getFirstName {
  my( $self ) = @_;
  return $self->{_firstName};
}
1;
  现在,在mail.pl文件创建Person对象如下
 #!/usr/bin/perl
use Person;
$object = new Person( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.
继承
  面向对象编程,有时涉及继承。继承仅仅意味着允许一个类被称为“子类“从另一个类继承方法和属性,调用父类, 这样你就不会一遍又一遍写相同的代码。例如,我们可以有一个Employee类继承自Person。 这被称为“是一个”的关系,因为雇员是一个人。Perl有一个特殊的变量@ISA来铺助,@ISA 管理(方法)继承。
  以下是使用继承说明
  Perl搜索指定对象的指定对象的类。
  Perl搜索类中定义的对象类的@ISA阵列。
  如果没有在步骤1和2找到方法,那么如果找到一个在@ ISA树,Perl使用AUTOLOAD子程序,
  如果仍然无法找到匹配的方法,那么Perl搜索的方法在通用类(包),标准的Perl库的一部分。
  如果方法还没有被发现,那么Perl放弃,并提出了一个运行时异常。
  因此,要创建一个新的Employee类将继承我们的Person类的方法和属性,我们简单的代码:保持将此程式码放入Employee.pm
 #!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person
  Employee类的所有方法和属性继承自Person类,你可以用它如下:使用main.pl文件来测试它
 #!/usr/bin/perl
use Employee;
$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.- by www.yiibai.com
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.
方法重载
  子类Employee继承了所有的方法从父类Person.但是,如果你想在你的子类中重写这些方法,那么你可以实现。在子类中,可以添加额外的函数。它可以做如下:修改Employee.pm文件:
 #!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person
# Override constructor
sub new {
  my ($class) = @_;
  # Call the constructor of the parent class, Person.
  my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
  # Add few more attributes
  $self->{_id}   = undef;
  $self->{_title} = undef;
  bless $self, $class;
  return $self;
}
# Override helper function
sub getFirstName {
  my( $self ) = @_;
  # This is child class function.
  print "This is child class helper function\n";
  return $self->{_firstName};
}
# Add more methods
sub setLastName{
  my ( $self, $lastName ) = @_;
  $self->{_lastName} = $lastName if defined($lastName);
  return $self->{_lastName};
}
sub getLastName {
  my( $self ) = @_;
  return $self->{_lastName};
}
1;
  现在把下面的代码到main.pl和执行它
 #!/usr/bin/perl
use Employee;
$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
This is child class helper function
Before Setting First Name is : Mohammad
This is child class helper function
After Setting First Name is : Mohd.
默认自动加载
  Perl提供了一个功能,你不会在其他许多编程语言找到:默认的子程序。
  如果你定义了一个函数调用AUTOLOAD(),那么任何未定义的子程序的调用将调用AUTOLOAD()函数。在此子程序$ AUTOLOAD缺少的子程序的名称。 这个功能是非常有用的错误处理的目的。下面是一个例子实现的AUTOLOAD,你可以使用自己的方式实现这个函数。
 sub AUTOLOAD
{
  my $self = shift;
  my $type = ref ($self) || croak "$self is not an object";
  my $field = $AUTOLOAD;
  $field =~ s/.*://;
  unless (exists $self->{$field})
  {
  croak "$field does not exist in object/class $type";
  }
  if (@_)
  {
  return $self->($name) = shift;
  }
  else
  {
  return $self->($name);
  }
}
析构函数和垃圾收集
  如果你已经编程使用对象之前,而你将意识到需要创建一个析构函数。当你使用完要释放分配的内存对象。Perl自动为您尽快的对象超出作用域。
  如果你想实现你的析构函数关闭文件,或做一些额外的处理,那么你需要定义一个特殊的方法,命名为destroy。 此方法会被调用的对象只是在Perl之前释放分配给它的内存。 在其他方面,就像其他DESTROY方法,可以操作任何你喜欢对象,以便正确地关闭它。
  析构函数的方法是简单地一个成员函数(子程序)命名的破坏都会被自动调用
 当对象的引用变量超出了作用域。  当对象引用的变量是未定义  当脚本结束  当Perl解释器终止
  有关实例:
 package MyClass;
...
sub DESTROY
{
  print "   MyClass::DESTROY called\n";
}
另一种面向对象实例
  这里是另一个很好的例子,这将有助于你了解面向对象的概念Perl。把这个源代码转换成任何文件,并执行它。
 #!/usr/bin/perl
# Following is the implementation of simple Class.
package MyClass;
sub new
{
  print "   MyClass::new called\n";
  my $type = shift;            # The package/type name
  my $self = {};               # Reference to empty hash
  return bless $self, $type;
}
sub DESTROY
{
  print "   MyClass::DESTROY called\n";
}
sub MyMethod
{
  print "   MyClass::MyMethod called!\n";
}
# Following is the implemnetation of Inheritance.
package MySubClass;
@ISA = qw( MyClass );
sub new
{
  print "   MySubClass::new called\n";
  my $type = shift;            # The package/type name
  my $self = MyClass->new;     # Reference to empty hash
  return bless $self, $type;
}
sub DESTROY
{
  print "   MySubClass::DESTROY called\n";
}
sub MyMethod
{
  my $self = shift;
  $self->SUPER::MyMethod();
  print "   MySubClass::MyMethod called!\n";
}
# Here is the main program using above classes.
package main;
print "Invoke MyClass method\n";
$myObject = MyClass->new();
$myObject->MyMethod();
print "Invoke MySubClass method\n";
$myObject2 = MySubClass->new();
$myObject2->MyMethod();
print "Create a scoped object\n";
{
  my $myObject2 = MyClass->new();
}
# Destructor is called automatically here
#by www.yiibai.com
print "Create and undef an object\n";
$myObject3 = MyClass->new();
undef $myObject3;
print "Fall off the end of the script...\n";
# Remaining destructors are called automatically here  
时间: 2024-08-09 01:23:36

浅谈Perl的类、包、模块与面对对象编程的相关文章

跟着百度学PHP[4]OOP面对对象编程-12-抽象类

什么是抽象方法?我们在类里面定义的没有方法体的方法就是抽象方法.所谓的没有方法体指的是,在方法声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时还要加一个关键字“abstract”来修饰. 目录==================================== 1.声明一个抽象类,抽象方法(案例一) 2.继承一个抽象类(实例二) ======================================= 案例一 <?php abstract

(C++)浅谈多态基类析构函数声明为虚函数

主要内容: 1.C++类继承中的构造函数和析构函数 2.C++多态性中的静态绑定和动态绑定 3.C++多态性中析构函数声明为虚函数 1.C++类继承中的构造函数和析构函数 在C++的类继承中, 建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推: 析构对象时,其顺序正好与构造相反: 具体参考文章:http://www.cnblogs.com/AndyJee/p/4575385.html 2.C++多态性中的静态绑定和动态绑定 对象的静态类型:对象在声明是采用的类型,在

浅谈Java工具类CommonUtils的使用

package com.xushouwei.cn; import java.util.HashMap; import java.util.Map; import org.junit.Test; import cn.itcast.commons.CommonUtils; /** * 测试CommonUtils类 * @author Administrator * */ public class CommonUtilsTest { /** * 测试:返回一个随机32位长得字符串 * CommonUt

浅谈python中处理时间的模块

我们知道,Python提供了三种时间函数,时间模块 time.基本时间日期模块 datetime 和日历模块 Calendar. 一.time模块 1.在time模块中,可以用三种表现形式来表示时间,分别是时间戳.格式化时间字符串和结构化时间: 1).时间戳,通过time.time()获得 >>> time.time() 1545027641.4434128 2).格式化时间字符串,通过类似于time.strftime("%Y-%m-%d %H:%M:%S")这样的表

浅谈JNDI导入jar包的先后次序影响程序运行结果的问题

今天下午我做了一个关于学生信息管理系统的demo,主要功能是使用jdbc对学生信息进行增删改查,整体的逻辑按照JNDI进行,使用oracle数据库. 第一次运行,果不其然出现了异常,参照下图: 经过检查,我发现我oracle的jar包导入路径错了,没有按照JNDI中的要求导入到tomcat文件夹下的lib文件夹中,而是导入到了项目的lib文件夹中.我向tomcat文件夹下的lib文件夹中添加了同名的jar包,我以为这样一来,程序就能正常运行了. 然而并没有. 异常还是这个异常,ClassNotF

浅谈java枚举类

先来一段常用枚举类代码结构 public enum Color { //枚举对象 RED(1,"红色"),GREEN(2,"绿色"),BLUE(3,"蓝色"); //私有成员属性 private int index; private String name; //私有构造方法 private Color(int index, String name) { this.index = index; this.name = name; } //公共的g

新人浅谈C++ string类

C++可以说时C语言的拓展,他兼容了C语言的很多优点,同时又有新的特性. 下面我们就来说一下C++里面的string类,string类是一个对字符串操作的类,在C语言中,定义字符串的方式一般为定义字符数组或指针.而在C++中,设计者将其封装到string这个类里面.方便进行一些操作. 下面我们以代码为例来进行string类型的一些常规操作进行解释说明 1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h

浅谈Java Object类

Java Object类 Object类是一个通用类,Java所有的类都是从Object类继承出来的.所以可将创建对象的过程理解为 public class Cars extends Object{ // 继承Object } Object类不是一个抽象类,部分方法是可以被覆盖的. Object类中有许多有用的方法 equals() 比较两个类是否相等 getClass() 告诉你对象是从哪里被初始化的 hashCode() 列出此对象的哈希代码 toString() 列出类的名称和一个我们不关

面对对象编程--类、继承

类(Class): 用来描述具有相同的属性和方法的对象的集合. 对象,实例:通过类实例化出来的东西 属性:类里面的变量 方法:类里面的方法 实例方法:正常定义的带self函数都是实例方法 类方法: 1.不实例化,直接用类名调用 2.它可以使用类变量,cls.xxx 3.实例也可以直接通过self.xx来使用类方法 4.类方法里面它是不能用这些实例方法和实例变量 静态方法: 就是一个普通的函数,只是定义在类里面而已. #用不了实例方法.用不了实例变量.也用不了类方法.类变量 #也不需要实例化,直接