唯一标识: 很明显,一个%employee 是不够的,每个雇员都要求有一个唯一标识和他或她自己的属性集合。 你可以动态的分配这个数据结构,也可以返回一个指向局部数据结构的引用 Vsftp:/root/perl/18# cat a1.pl use Data::Dumper; sub new_employee { my ($name,$age,$starting_position)=@_; my $r_employee = { ##使用匿名散列表 "name" =>$name, #创建一个唯一的对象 "age" =>$age, "position" =>$starting_position }; return $r_employee; ##返回对象 }; $emp1 = new_employee("John Doe","32","Software Engineer"); print Dumper($emp1); print " "; Vsftp:/root/perl/18# perl a1.pl $VAR1 = { 'position' => 'Software Engineer', 'name' => 'John Doe', 'age' => '32' }; Vsftp:/root/perl/18# cat Employee.pm package Employee; sub new { my $class = shift; my $self={ @_ }; bless $self,$class; return $self; }; sub promote { my $self=shift; my $a=shift; my $b=shift; return $a + $b; }; 1; Vsftp:/root/perl/18# cat a2.pl unshift(@INC,"/root/perl/18"); use Employee; use Data::Dumper; my $emp=Employee->new("name"=>"John","age"=>"32","position"=>"dada"); print Dumper($emp); print " "; print "11111111111111111 "; print $emp->promote(33,44); print " "; print "2222222222222222 "; print Employee::promote($emp,45,56); print " "; Vsftp:/root/perl/18# perl a2.pl $VAR1 = bless( { 'position' => 'dada', 'name' => 'John', 'age' => '32' }, 'Employee' ); 11111111111111111 77 2222222222222222 101 方法的第一个参数为对象 现在我们使用箭头记号来直接调用实例的方法,或者用面向对象的话说,调用对象的方法: print $emp->promote(33,44); 直接调用 当Perl 看到$emp->promote(33,44)时,它会决定$emp 属于哪个类(也就是在其中执行bless的) 在这里是Employee perl 于是就会如下调用这个函数 Employee::promote($emp,45,56); 换句话说,箭头左边的对象 只是作为相应子例程的第一个参数。 在与C++ 中不同,记号:: 和->实际上都是允许的。Perl的实例方法没有什么神奇的地方 它只是第一个参数碰巧为对象引用的普通子过程 ref 函数返回一个表示引用所指向实体类型的字符串,而对于经过bless的对象引用,它返回相应类的名字。 类方法和属性: 类属性只是包的全局变量,类方法则是不依赖任何特地实例的普通子例程。 回想一下实例方法的情况,箭头左边的对象将作为该子例程的第一个参数传递。 这里也是一样,过程HourlyEmployee::new 同样需要重写程下面这种期望的形式: 因为实例和类方法都是普通的子例程,因此你总是可以通过检查所传递的第一个参数的类型 编写一个子例程 使它具有它们任何一个的功能。 如果第一参数为类,那么就是类方法 如果第一个参数为对象,那么就是对象方法 如果我们在编写类方法时,都默认以模块的名字为它的第一个参数的话 迂回策略:一种间接的记号: 继承的必要性: Perl 允许一个模块在一个特殊的名为@ISA 的数组中指定一组其他模块的名称。 当你模块中找不到某个类或实例方法时,它就会检查那个模块的@ISA是否被初始化 如果初始化,它就会查看其中的某个模块是否支持这个"缺少"的函数 这个特性被称为 继承 重载基类: