• 第十二章 对象(上)


    第十二章 对象(上)
    
    对象是一个数据结构, 带有一些行为。我们通常把这些行为成为对象的直接动作,
    
    
    类和实例方法 通过第一个参数区分,对于 Perl 而言,方法就是方法,只是由其第一个参数的类型来区分。
    
    
    一个类可以从父类中继承方法,父类也叫基类或者超级类。
    
    
    原则--所有对象的访问都应该只通过方法,
    
    
    12.2 Perl 的对象系统
    
    
    一个对象只不过是一个引用...恩,就是引用。
    
    因为引用令独立的标量代表大量的数据,
    
    
    一个类只是一个包
    
    
    一个包当作一个类——通过使用包的子过程来执行类的方法,以及通过使用包的 变量来保存类的全局数据。通常,
    使用一个模块来保存一个或者更多个类。
    一个方法只是一个子过程
    
    
    12.3 方法调用
    
    如果用一个类调用该方法,那个参数 将会是类的名字。如果用一个对象调用方法,那个参数就是对象的引用。
    
    
    对于类方法而言,调用者是包的名字。对于一个实例方法,调用者是 调用
    者是一个声明对象的引用
    
    
    12.3.1 使用箭头操作符的方法调用
    INVOCANT->METHOD(LIST)
    INVOCANT->METHOD
    
    
    INVOCANT 是一个包的 名字的时候,我们把那个被调用的METHOD 看作类方法。
    
    比如,使用类方法 summon 的构造一个类,然后在生成的对象上调用实例方法 speak,你 可以这么说:
    
    $mage = Wizard->summon("Gandalf"); # 类方法
    $mage->speak("friend")  # 实例方法
    
    
    
    12.3.2 使用间接对象的方法调用
    
    
    12.3.4 引用包的类
    
    12.4 构造对象
    
    所有对象都是引用,但不是所有引用都是对象
    
    把一个引用和一个包名字标记起来(因此也和 包中的类标记起来了,因为一个类就是一个包)
    的动作被称作赐福(blessing),你可以把 赐福(bless)看作把一个引用转换成一个对象
    
    
    bless 函数接收一个或者两个参数。第一个参数是一个引用,而第二个是要把引用赐福 (bless)成的包。如果忽
    略第二个参数,则使用当前包。
    
    Vsftp:/root/perl/8# cat Critter.pm 
    package Critter;
    sub new {
    my $self = {'a'=>11,'b'=>22}; # 指向一个空的匿名散列
    bless $self, "Critter"; # 把那个散列作成一个 Critter 对象
    return $self; # 返回新生成的 Critter
    };
    1;
    Vsftp:/root/perl/8# cat a1.pl 
    unshift(@INC,"/root/perl/8");
    use Critter;
    use Data::Dumper;
    $pet = Critter->new;
    print Dumper($pet);
    print "
    ";
    print $pet->{"a"};
    print "
    ";
    
    Vsftp:/root/perl/8# perl a1.pl 
    $VAR1 = bless( {
                     'a' => 11,
                     'b' => 22
                   }, 'Critter' );
    
    11
    
    
    12.4.1 可继承构造器
    
    和所有方法一样,构造器只是一个子过程,但是我们不把它看做一个子过程。
    
    在这里例子里,我们总是把它当作一个方法来调用
    
    ---类方法,因为调用者是一个包名字。
    
    
    方法调用和普通的子过程调用有两个区别。
    
    12.4.2 初始器
    
    Vsftp:/root/perl/8# cat a2.pl 
    sub fun1 {
           print "@_ is @_
    ";
          my $a1=shift;
          print "$a1 is $a1
    ";
           print "@_ is @_
    ";
        };
    fun1(1,2,43,434);
    Vsftp:/root/perl/8# perl a2.pl 
    @_ is 1 2 43 434
    $a1 is 1
    @_ is 2 43 434
    
    
    sub new {
    my $invocant = shift;  ##从@_中取出第一个元素 类的名字
    my $class = ref($invocant) || $invocant;
    my $self = { @_ }; # 剩下的参数变成属性
    bless($self, $class); # 给予对象性质
    return $self;
    }
    
    Vsftp:/root/perl/8# cat Horse.pm 
    package Horse;
    sub new {
    print "@_ is @_
    ";
    my $invocant = shift;  ##从@_中取出第一个元素 类的名字
    print "$invocant is  $invocant
    ";
    print "@_ is @_
    ";
    my $class = ref($invocant) || $invocant;
    my $self = { @_ }; # 剩下的参数变成属性
    bless($self, $class); # 给予对象性质
    return $self;
    };
    1;
    
    Vsftp:/root/perl/8# cat a3.pl 
    unshift(@INC,"/root/perl/8");
    use Horse;
    use Data::Dumper;
    $stallion = Horse->new(color => "black");
    print Dumper($ed);
    
    
    Vsftp:/root/perl/8# perl a3.pl 
    @_ is Horse color black
    $invocant is  Horse
    @_ is color black
    $VAR1 = undef;
    
    
    
    12.5 类继承
    
    对Perl的对象系统剩下的内容,从一个类继承另外一个类并不要给这门语言增加特殊的语法。
    
    当你调用一个方法,如果perl 在调用者的包里找不到这个子过程,那么它就检查@ISA数组
    
    Horse类继承Critter (父类 或称为基类):
    
    Vsftp:/root/perl/9# cat Horse.pm 
    package Horse;
    our @ISA = "Critter";
    sub new {
    my $invocant = shift;
    my $class = ref($invocant) || $invocant;
    my $self = {
    color => "bay",
    legs => 4,
    owner => undef,
    @_, # 覆盖以前的属性
    };
    return bless $self, $class;
    };
    sub sum_arr {
           $self=shift;
           my $a=shift;
           my $b=shift;
           return $a + $b + 7;
    };
    1;
    Vsftp:/root/perl/9# 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 sum {
           $self=shift;
           my $a=shift;
           my $b=shift;
           return $a + $b;
    };
    1;
    Vsftp:/root/perl/9# cat a1.pl 
    unshift(@INC,"/root/perl/9"); 
    use Horse;;
    use Critter;
    use Data::Dumper;
    $ed = Horse->new; # 四腿湾马
    print $ed->sum_arr(4,5);
    print "
    ";
    print $ed->sum(4,5);
    print "
    ";
    
    Vsftp:/root/perl/9# perl a1.pl 
    16
    9
    
    你现在应该可以在原先Critter 使用的任何地方使用Horse类或者对象了
    
    
    
    
    当你调用一个方法的时候,如果 Perl 在调用者的包里找不到这个子过程, 那么它就检查 @ISA 数组(
    
    
    Perl 是这样实现继承的:一个包的 @ISA 数组里的每个元素都保存另外一个包的名字,
    
    
    package Horse;
    our @ISA = "Critter";
    
    把 Horse 类变成 Critter 类的子类
    
    Critter  是父类或者称为基类
    
    假设你在 $steed 里有一个 Horse 对象,并且在他上面调用了一个 move:
    $steed->move(10);
    因为 $steed 是一个 Horse,Perl 对该方法的第一个选择是 Horse::move 子过程。如果 没有,Perl 先询问
    @Horse::ISA 的第一个元素,而不是生成一个运行时错误,这样将导致 查询到 Critter 包里,并找到
    Critter::move。如果也没有找到这个子过程,而且 Critter 有自己的 @Critter::ISA 数组,那么继续查询那里面
    的父类,看看有没有一个 move 方法,如此类推直到上升到继承级别里面一个没有 @ISA 的包

  • 相关阅读:
    使用递归方式判断某个字串是否是回文( palindrome )
    方法的动手动脑
    设计统计英文字母出现频率的感想
    原码、补码、反码
    java语法基础报告
    人月神话阅读笔记01
    第六周学习进度报告--(大二下)
    第五周学习进度报告--(大二下)
    梦断代码阅读笔记03
    个人作业--数组之首尾相连
  • 原文地址:https://www.cnblogs.com/zhaoyangjian724/p/6198958.html
Copyright © 2020-2023  润新知