<pre name="code" class="html">第十二章对象(上): $ed=x1->new('lily','29') 当Perl 看到$ed->sum_var(99,5); 时,它会决定$ed属于哪个类(也就是在其中执行bless的) 在这里,它是x1. Perl于是就会如下所示调用这个函数 x1::sum_var($ed) 换句话说,箭头左边的对象只是作为相应子程序的第一个参数。 对象是一个数据结构,带有一些行为。 我们通常把这些行为成为对象的直接动作, 适用于某一个特定对象的方法叫做实例方法 适用于整个类的方法叫做类方法 类里面那 些生成 对象实例的方法叫构造方法 一个类可以从父类中继承方法,父类也叫基类或者超级类 12.2 Perl 的对象系统 一个对象只不过是一个引用...恩,就是引用。 因为引用令独立的标量代表大量的数据,所以我们不应该对把引用用于所有对象 感到奇怪 一个类只是一个包 一个包当作一个类——通过使用包的子过程来执行类的方 12.3 方法调用 Perl 总是会给 构成这个方法的子过程传递一个额外的初始化参数 如果用一个类调用该方法,那个参数 将会是类的名字 [root@wx03 test]# cat p1.pm package p1; use base qw(p2); use Data::Dumper; sub new { my $self = {}; my $invocant = shift; ##第一个参数类的名字 my $class = ref($invocant) || $invocant; my ($name)=@_; my $self = { "name" =>$name }; bless $self, $class; # Use class name to bless() reference print "111111111111111111 "; $str=Dumper($self); print "$str is $str "; return $self; } 如果用一个对象调用方法,那个参数就是对象的引用。 sub setBeanType{ my ($self, $name) = @_;##//传进来的第一个参数是类似c++的self指针,第二个才是真正的参数 $self->{'Bean'} = $name; 对于类方法而言,调用者是包的名字。对于一个实例方法,调用者是 调用 者是一个声明对象的引用 12.3.1 使用箭头操作符的方法调用 INVOCANT->METHOD(LIST) INVOCANT->METHOD (请不要把->和=>混淆,“双管”箭头起 神奇逗号的作用。) [root@wx03 test]# cat t5.pl %hash=(a,1,b,2,c,3); print %hash; print " "; %hash=(a=>1,b=>2,c=>3); print %hash; print " "; [root@wx03 test]# perl t5.pl b2c3a1 b2c3a1 比如,使用类方法 summon 的构造一个类,然后在生成的对象上调用实例方法 speak,你 可以这么说: $mage = Wizard->summon("Gandalf"); # 类方法 $mage->speak("friend"); # 实例方法 12.3.2 使用间接对象的方法调用 12.3.4 引用包的类 12.4 构造对象 所有对象都是引用,但不是所有引用都是对象。 把一个引用和一个包名字标记起来 的动作成为bless 可以把bless 看作把一个音乐转换成一个对象 bless 函数接收一个或者两个参数。第一个参数是一个引用,而第二个是要把引用赐福 (bless)成的包。如果忽 略第二个参数,则使用当前包。 $obj = { }; # 把引用放到一个匿名散列 bless($obj); # Bless 散列到当前包 bless($obj, "Critter"); # Bless 散列到类 Critter 这里我们使用了一个指向匿名散列的引用 因为一个类就是一个包 $obj = { }; # 把引用放到一个匿名散列 bless($obj); # Bless 散列到当前包 bless($obj, "Critter"); # Bless 散列到类 Critter。 $obj = { }; 这里我们使用了一个指向匿名散列的引用, 也是人们通常拿来做他们的对象的数据结构的 东西 如果你在 使用一个类,你要做的甚至更少,因为类的作者会 把 bless 隐藏在一个叫构造器的方法 里,它创建和返回类的实例。 package Critter; sub spawn { my $self = {}; # 指向一个空的匿名散列 bless $self, "Critter"; # 把那个散列作成一个 Critter 对象 return $self; # 返回新生成的 Critter } 有了那个定义,下面就是我们如何创建一个 Critter 对象了: $pet = Critter->spawn; 12.4.1 可继承构造器: 和所有方法一样,构造器只是一个子过程,但是我们不把它看作一个子过程。在这个例子 里,我们总是把它当作一 个方法来调用——一个类方法,因为调用者是一个包名字。 类方法调用者是字符串 类名字 对象方法调用者是引用 是对象 12.4.2 初始器 大多数对象维护的信息是由对象的方法间接操作的。到目前为止我们的所有构造器都创建了 空散列,但是我们没有 理由让它们这么空着。比如,我们可以让构造器接受额外的参数, 并且把它们当作键字/数值对。 [root@wx03 test]# cat test.pm package test; sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { color => "bay", legs => 4, owner => undef, @_, # 覆盖以前的属性 }; return bless $self, $class; #return $self; }; sub clone { my $model = shift; print %$model; print " "; my $hash=%$model; $hash{name}="bmw"; my $self = $model->new(%hash, @_); return $self; # 前面被 ->new 赐福过了 }; 1; [root@wx03 test]# cat t11.pl unshift(@INC,"/root/test"); use test; $ua=test->new(); use Data::Dumper; $str=Dumper($ua); print "$str is $str "; $var1=$ua->clone(); $str=Dumper($var1); print "$str is $str "; [root@wx03 test]# perl t11.pl $str is $VAR1 = bless( { 'color' => 'bay', 'owner' => undef, 'legs' => 4 }, 'test' ); colorbayownerlegs4 $str is $VAR1 = bless( { 'color' => 'bay', 'owner' => undef, 'legs' => 4, 'name' => 'bmw' }, 'test' ); 12.5 类继承