唯一标识:
很明显,一个%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 "\n";
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 "\n";
print "11111111111111111\n";
print $emp->promote(33,44);
print "\n";
print "2222222222222222\n";
print Employee::promote($emp,45,56);
print "\n";
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是否被初始化
如果初始化,它就会查看其中的某个模块是否支持这个"缺少"的函数
这个特性被称为 继承
重载基类: