zoukankan      html  css  js  c++  java
  • 第十二章 对象(上)

    第十二章 对象(上)
    
    对象是一个数据结构, 带有一些行为。我们通常把这些行为成为对象的直接动作,
    
    
    类和实例方法 通过第一个参数区分,对于 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 的包

  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13350003.html
Copyright © 2011-2022 走看看