对象(上):

  对象(上):

对象是一个数据结构,带有一些行为。

 如果需要区分上面两种情况, 那么我们就把适用于某一特定对象的方法叫做实例
方法,而把那些适用于整个类的方法叫做类方法。不过这样做只是为了方便——对于 Perl
而言,方法就是方法,只是由其第一个参数的类型来区分。

类方法 第一个参数为类

对象方法 第一个参数为对象

类里面那些生成对象实例的方
法叫构造方法

 Perl的对象系统:

一个对象只不过是一个引用...恩,就是引用。
因为引用令独立的标量代表大量的数据, 所以我们不应该对把引用用于所有对象 感到奇怪。 


方法调用:
不管使用哪种方法调用的形式,Perl 总是会给
构成这个方法的子过程传递一个额外的初始化参数。

如果用一个类调用该方法, 那个参数将
会是类的名字。如果用一个对象调用方法,那个参数就是对象的引用。


OO 的核心是下面这样简单的逻辑:一旦得知调用者,则可以
知道调用者的类,而一旦知道了类,就知道了类的继承关系,一旦知道了类的继承关系,那
么就知道实际调用的子过程了。


使用箭头操作符的方法调用:

我们说过有两种风格的方法调用。第一种调用方法的风格看起来象下面这样:

INVOCANT->METHOD(LIST)
INVOCANT->METHOD


当 INVOCANT 是一个
包的名字的时候,我们把那个被调用的 METHOD 看作类方法。


比如,使用类方法 summon 的构造一个类,然后在生成的对象上调用实例方法 speak,
你可以这么说:

$mage = Wizard->summon("Gandalf"); # 类方法  类方法的参数是类 Wizard
$mage->speak("friend"); # 实例方法



使用间接对象的方法调用:


间接对象的句法障碍:

 引用包的类:

构造对象

可继承构造器:

和所有方法一样, 构造器只是一个子过程, 但是我们不把它看作一个子过程。 在这个例子里,
我们总是把它当作一个方法来调用——一个类方法, 因为调用者是一个包名字。



[root@wx03 5]# cat hui.pm 
package hui;

 sub new {
my $class=shift;
my $self = { };
bless ($self, $class);
return $self;
};

sub spawn {
my $invocant = shift;
print "\$invocant is $invocant\n";
my $class = ref($invocant) || $invocant; # 对象或者类名字 如果是对象 取类的名字
print "\$class is $class\n";
my $self = { };
bless ($self, $class);
return $self;
};
1;
[root@wx03 5]# cat a2.pl 
use hui;
$ua=hui->new();
print $ua;
print "\n";
$ua->spawn;
[root@wx03 5]# perl a2.pl 
hui=HASH(0xd8d160)
$invocant is hui=HASH(0xd8d160)
$class is hui








初始器:

sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = { @_ }; # 剩下的参数变成属性
bless($self, $class); # 给予对象性质
return $self;
}


更灵活一些,你可以用缺省键字/数值对设置你的构造器,这些参数可以由用户在使用的时
候通过提供参数而覆盖掉:

[root@wx03 5]# cat Horse.pm 
package Horse;
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = {
color => "bay",
legs => 4,
owner => undef,
@_, # 覆盖以前的属性
};
return bless $self, $class;
};
1;
[root@wx03 5]# cat a3.pl 
use Horse;
$ed = Horse->new;
use Data::Dumper;
$str=Dumper($ed);
print "\$str is $str\n";

$stallion = Horse->new(color => "black"); # 四腿黑马
$str=Dumper($stallion);
print "\$str is $str\n";
[root@wx03 5]# perl a3.pl 
$str is $VAR1 = bless( {
                 'owner' => undef,
                 'legs' => 4,
                 'color' => 'bay'
               }, 'Horse' );

$str is $VAR1 = bless( {
                 'owner' => undef,
                 'legs' => 4,
                 'color' => 'black'
               }, 'Horse' );


当把这个 Horse 构造器当作实例方法使用的时候,它忽略它的调用者现有的属性。


任何碰巧创建和返回一个对象的方法都是实际上的构造器


perl 把对象转换成散列:

[root@wx03 5]# cat a4.pl 
use Horse;
use Data::Dumper;

$steed = Horse->new(color => "dun");
$str=Dumper($steed);
print "\$str is $str\n";

print "111111111111\n";
print %$steed;

print "\n";

print "2222222222\n";

%hash=%$steed;
print $hash{color};
print "\n";

[root@wx03 5]# perl a4.pl 
$str is $VAR1 = bless( {
                 'legs' => 4,
                 'owner' => undef,
                 'color' => 'dun'
               }, 'Horse' );

111111111111
legs4ownercolordun
2222222222
dun


//**********

sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = {
color => "bay",
legs => 4,
owner => undef,
@_, # 覆盖以前的属性
};
return bless $self, $class;
}


sub clone {
my $model = shift;
my $self = $model->new(%$model, @_);  ##把$model对象转成hash,@_ 是传入的参数 这里是owner => "EquuGen Guild, Ltd."

#$model 作为new的第一个参数,会提取类名

return $self; # 前面被 ->new 赐福过了
}


类继承:


Perl 是这样实现继承的:一个包的@ISA 数组里的每个元素都保留另外一个包的名字,

当缺失方法的时候就搜索这些包。

比如,下面的代码把Horse类变成Critter类的子类。

(我们用our声明@ISA,因为它必须是一个包变量,而不能是my声明的词法作用域变量)。

package Horse;
our @ISA = "Critter";

你现在应该可以在原先Critter使用的任何地方使用Horse类或者对象了。

如果你的新类通过了这样的空子类测试,那么你就可以认为Critter是一个正确的基类,

可以用于继承。

[root@wx03 5]# cat Critter.pm 
package Critter;  
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  
    return $self;  
  
};  
  
sub sum2 {  
       $self=shift;  
       my $a=shift;  
       my $b=shift;  
       return $a + $b;  
};  
  
  
sub fun1 {  
       $self=shift;  
       my $a=shift;  
       my $b=shift;  
       return $a / $b;  
}  
1;  
[root@wx03 5]# cat a4.pl 
use Horse;
use Data::Dumper;

$steed = Horse->new(color => "dun");
print $steed->fun1(10,2);
print "\n";
[root@wx03 5]# perl a4.pl 
5




你现在应该可以在原先 Critter 使用的任何地方使用 Horse 类或者对象了。











posted @ 2016-05-31 09:51  czcb  阅读(139)  评论(0编辑  收藏  举报