面向对象的Perl 之二

Perl语言的面向对象编程 Perl是一种功能强大的脚本语言,以其灵活性和强大的文本处理能力而闻名。虽然Perl主要以其程序设计范式(如过程式编程和功能性编程)而广为人知,但它同样支持面向对象编程(OOP)。通过本篇文章,我们将深入探讨Perl语言中的面向对象编程,了解其基本概念、实现方式,以及如何在实际开发中应用这些概念。 阅读详情
14.2.8 多态性和动态绑定
Webster 辞典把多态性(polymorphism)定义为:
polymorphism: n. 1. the state or condition of being polymorphous。
为了说的更清楚些,下面是另一个定义:
具有多种形态或采取多种行为方式的能力... 同一个操作在不同的类中表现为不同的行为。
多态性拥有很多种不同的描述方式,它早已隐含在了OO 语境中。
在Perl 中,它的意思是可以使用同一个名称在不同的类中提供同一种方法,
而在调用方法时,它会自动进行正确的选择;
换而言之,当通过对象引用调用方法时,它将进入对象所属的类中。
下面这个示例14.10 说明了多态性的特点。
这里用到了两个模块Cat.pm 和Dog.pm,
每个模块都含有三个同名函数:new、set_attributes 和get_attributes。
示例14.10 中的驱动程序(或用户程序)将使用这两个模块。
当调用各自的类构造函数时,便能返回指向cat 或dog 对象的引用。
当使用对象引用来访问方法时,Perl 会知道调用的子例程及其所属的类,即使方法出现重名也不要紧。
Perl确定了待调用对象所属的类,并在该类(包)中搜寻调用的方法。
这里调用正确方法的能力就展示出所谓的多态性。
动态绑定又称为运行时绑定(runtime binding),它能允许程序推迟调用正确的方法,直到程序开始执行。
它与多态性一起负责将正确的方法绑定到关联的类上,而不必通过if 语句来决定需要调用的方法。
这样就提供了很大的灵活性,并且这对继承机制的正确性也是非常必要的。
若要利用多态性和运行时绑定,就必须使用面向对象的语法,而不是传统的:: 语法。
例如,倘若由两个类Director 和Rifleman,它们均含有方法shoot。
用户可以把它写成$object->shoot,而Perl 会知道对象所属的类。它会在编译时确定正确的类。
通过这种方式,Director 就不会在分配角色时射出子弹,而Rifleman 也不会尝试拍摄有关步枪射击的电影。
读者还可以添加其他的类,
譬如含有不同shoot 方法的BasketballPlayer 类,并能确保对于该类也能调用正确的方法。
如果没有运行时绑定和多态机制的话,程序就只能根据某种条件判断的结果才能确定该用哪个正确的类,
譬如:
if ( ref($object1) eq "Director") {
     Director::shoot($object1);
elsif ( ref($object2) eq "Rifleman" ){
     Rifleman::shoot($object2);
else{
     BasketballPlayer::shoot($object3);
}
在面向对象的语法中,Perl 会隐式地将指向对象的一个引用作为参数传递给方法。
由于Perl 会把对象引用传递当作第一个参数传递给访问方法,并且该对象也已经归入到合适的类里,
因此Perl能够实现多态性,并作出正确的选择!
假定在示例14.10 中创建的$object1 对象属于Director 类,
$object2 对象属于Rifleman 类,而$object3 则属于BasketballPlayer 类。
$object1->shoot;evaluates to Director::shoot($object1);
$object2->shoot;evaluates to Rifleman::shoot($object2);
$object3->shoot;evaluates to BasketballPlayer::shoot($object3)


示例14.10
( File: Cat.pm)
1 package Cat;
2 sub new{             # Constructor
      my $class=shift;
      my $dptr={};
      bless($dptr, $class);
  }
3 sub set_attributes{  # Access Methods
      my $self= shift;
4     $self->{"Name"}="Sylvester";
      $self->{"Type"}="Siamese"; 
      $self->{"Sex"}="Male";
  }
5 sub get_attributes{
      my $self = shift;
      print "-" x 20, "\n";
      print "Stats for the Cat\n";
      print "-" x 20, "\n";
      while(($key,$value)=each( %$self)){
        print "$key is $value. \n";
   }
   print "-" x 20, "\n";
1;
--------------------------------------------------------------------


(File: Dog.pm)
6 package Dog;
7 sub new{       # Constructor
      my $class=shift;
      my $dptr={};
      bless($dptr, $class);
  }
8 sub set_attributes{
      my $self= shift;
9     my($name, $owner, $breed)=@_;
10    $self->{"Name"}="$name";
      $self->{"Owner"}="$owner";
      $self->{"Breed"}="$breed";
   }
11 sub get_attributes{
      my $self = shift;
      print "x" x 20, "\n";
      print "All about $self->{Name}\n";
      while(($key,$value)= each( %$self)){
        print "$key is $value.\n";
      }
      print "x" x 20, "\n";
    }
1;
--------------------------------------------------------------------


解释
1. 这是模块Cat.pm 中对一个名叫Cat 的类的包声明。
2. Cat 类的构造函数方法名为new。本行会把一个Cat 对象归入到类中。
3. 访问方法set_attributes,定义Cat 对象的数据属性。
4. 使用对象指针$ref 给Cat 对象赋予一个键/ 值对,以便指定它的名字。
5. 使用另一个访问方法get_attributes 显示Cat 对象。
6. 在另一个文件Dog.pm 中,对一个名叫Dog 的类提供包声明。
7. 与Cat 类一样,Dog 类也有一个名叫new 的构造函数。本行会把一个Dog 对象归入到类中。
8. 访问方法set_attributes,定义Dog 对象的数据属性。
9. 从驱动程序中传递Dog 对象的属性,并赋值给@_ 数组。
10. 使用对象指针$ref 给Dog 对象赋予一个键/ 值对,以便指定它的名字。
11. 与Cat 类一样,使用另一个访问方法get_attributes 显示Dog 对象内容。


(The Script: driver program for Example 14.10)
#!/bin/perl
1 use Cat; # Use the Cat.pm module
2 use Dog; # Use the Dog.pm module
3 my $dogref = Dog->new; # Polymorphism
4 my $catref= Cat->new;
5 $dogref->set_attributes("Rover", "Mr. Jones", "Mutt");
6 $catref->set_attributes; # Polymorphism
7 $dogref->get_attributes;
8 $catref->get_attributes;


(Output)
xxxxxxxxxxxxxxxxxxxx
All about Rover
Owner is Mr. Jones.
Breed is Mutt.
Name is Rover.
xxxxxxxxxxxxxxxxxxxx
--------------------
Stats for the Cat
--------------------
Sex is Male.
Type is Siamese.
Owner is Mrs. Black.
Name is Sylvester.
--------------------
解释
1. use 指令负责加载Cat.pm 模块。
2. use 指令加载Dog.pm 模块。现在程序便可访问这两个类了。
3. 调用new 构造函数。
   其第一个参数是类名Dog,Perl 会将其翻译为Dog::new(Dog)。返回的是指向Dog 对象的引用。
   Perl 知道这个引用是属于Dog 类的,因为已经在构造函数中对它完成了归入(bless)处理。
   创建Dog 对象的实例。
4. 调用构造函数方法new,
   并把类名作为第一个参数传递给它。返回指向Cat 对象的引用。
   Perl会将方法调用翻译为Cat::new(Cat)。上述两个类都用到了new 函数,
   但由于Perl 知道该方法各自所属的类,因此始终能够调用正确的new 函数。这就是多态性的一个例子。
5. 有了指向对象的引用后,通过该引用调用访问方法(实例方法)。
   Perl 会把 $dogref->set_attributes
   翻译为    Dog::set_attributes( $dogref, "Rover", "Mr. Jones", "Mutt" )。
6. 这一次,调用cat 对象的set_attributes 方法。Cat 类会设置cat 的属性。
7. 调用get_attributes 方法显示Cat 类的数据属性。
8. 调用get_attributes 方法显示Dog 类的数据属性。


:: 和-> 标记。箭头-> 语法一般用在拥有多态性、动态绑定和继承行为的面向对象程序中。这
里也可以使用:: 语法,但后者更不灵活,而且如果不使用条件语句的话还会出问题。下面的示例中
展示了:: 语法的缺点。如果使用面向对象的语法,就不会出现这些问题了。


示例14.12
# The Cat class
package Cat;
sub new{                # The Cat's constructor
  my $class = shift;
  my $ref = {};
  return bless ($ref, $class);
}


sub set_attributes{     # Giving the Cat some attributes,
                        # a name and a voice
  my $self = shift;
  $self->{"Name"} = "Sylvester";
  $self->{"Talk"}= "Meow purrrrrr.... ";
}


sub speak { # Retrieving the Cat's attributes
  my $self = shift;
  print "$self->{Talk} I'm the cat called $self->{Name}.\n";
}
1;
---------------------------------------------------------------------


# The Dog class
package Dog; # The Dog's Constructor
sub new{
  my $class = shift;
  my $ref = {};
  return bless ($ref, $class);
}


sub set_attributes{ # Giving the Dog some attributes
  my $self = shift;
  $self->{"Name"} = "Lassie";
  $self->{"Talk"}= "Bow Wow, woof woof.... ";
}


sub speak { # Retrieving the Dog's attributes
  my $self = shift;
  print "$self->{'Talk'} I'm the dog called $self->{'Name'}.\n";
}
1;
---------------------------------------------------------------------


#!/bin/perl
# User Program
# This example demonstrates why to use the object-oriented
# syntax rather than the colon-colon syntax when passing
# arguments to methods.
use Cat;
use Dog;
$mydog = new Dog; # Calling the Dog's constructor
$mycat = new Cat; # Calling the Cat's constructor
$mydog->set_attributes; # Calling the Dog's access methods
$mycat->set_attributes; # Calling the Cat's access methods
2 $mycat->speak;
3 print "\nNow we make a mistake in passing arguments.\n\n";
4 Cat::speak($mydog); # Perl goes to the Cat class to find the
                      # method, even though attributes have been
                      # set for the dog!


(Output)
1 Bow Wow, woof woof.... I'm the dog called Lassie.
2 Meow purrrrrr.... I'm the cat called Sylvester.
3 Now we make a mistake in passing arguments.
4 Bow Wow, woof woof.... I'm the cat called Lassie.


解释
1. 以面向对象方式调用speak 方法,保证了Perl 能将该方法与归属类绑定在一起。
   将指向Dog 对象的引用作为第一个参数传递给speak 方法。Perl 会把它翻译为Dog::speak($mydog)。
   Perl 会在编译时确定使用的类,因此在调用speak 方法时能把它绑定到正确的类上面去。
2. 将指向Cat 对象的引用作为第一个参数传递给speak 方法。Perl 会把它翻译为Cat::speak($mycat)。
3. 下面的代码会把dog 引用传递给Cat 包。如果使用面向对象的方法,则不会出现这种错误,
   因为Perl 始终能确定方法所属的类,并调用正确的方法。该特性称为多态性或运行时绑定。
4. 通过使用:: 标记,Perl 会在运行时识别正确的类,并使用Cat 类中的speak 方法,即传送的
   是指向Dog 对象的引用。


14.2.9 析构函数和垃圾收集
Perl 维护了对大量对象引用的跟踪信息,并在引用计数达到0 时自动销毁该对象。在退出程序
时,Perl 会销毁与程序相关联的每一个对象,从而处理无用存储单元,并释放其使用过的内容。因
此用户无需关心内存清理事宜。不过,用户也可在程序中定义DESTROY 方法,以便在销毁对象
前控制该对象。


示例14.13
(The Class)
1 package Employee;
  sub new{
    my $class = shift;
    $ref={};
    bless($ref, $class);
    return $ref;
  }
2 sub DESTROY{
    my $self = shift;
3   print "Employee $self->{Name} is being destroyed.\n";
  }
1;
---------------------------------------------------------------


#!/usr/bin/perl
# User of the class
4 use Employee;
5 my $emp1 = Employee->new; # Create the object
6 { my $emp2 = Employee->new;
    $emp2->{"Name"}="Christian Dobbins";
    print "\t\t$emp2->{'Name'}\n";
  } # Create the object
7 my $emp3 = Employee->new; # Create the object
8 $emp1->{"Name"}="Dan Savage";
  $emp3->{"Name"}="Willie Rogers";
  print "Here are our remaining employees:\n";
  print "\t\t$emp1->{'Name'}\n";
  print "\t\t$emp3->{'Name'}\n";


(Output)
Christian Dobbins
Employee Christian Dobbins is being destroyed.
Here are our remaining Employees:
Dan Savage
Willie Rogers
Employee Dan Savage is being destroyed.
Employee Willie Rogers is being destroyed.


解释
1. 声明Employee 类,并定义其构造函数方法。
2. 当不再需要某个Employee 对象时,便会调用其DESTROY 方法,并打印本行内容。第6 行
   出现的对象是在一个代码块中定义的。当退出该代码块时,该对象也应予以销毁。当程序结
   束时,另一个对象也将销毁。
3. 每当对象得以销毁时,打印本行内容。
4. 这里将使用Employee 模块。
5. 通过调用构造函数方法,创建一个新的Employee 对象,得到其对象引用$emp1。
6. 在同一代码块中创建另一个Employee 对象。为该对象赋予一个“名字”,即Christian Dobbins。
   由于它是一个“my”变量,因此其作用域是受限的。也就是说,在退出该代码块时,这个对
   象也将予以销毁。这时便会调用DESTROY 方法,将它清除出内存。
7. 通过调用构造函数方法,创建第三个Employee 对象,它由$emp3 来引用。
8. 为Employee 对象赋予键/ 值对。
perl中的面向对象 node1:/root/20200608#cat Client.pm package Client; use Data::Dumper; sub new{ ##包的名字 my $class= shift; print "\$class==$class.\n"; my %p = @_; my $self={ 'aa'=>$p{'name'}, 'bb'=>$p{'x'}, 'cc'=>$p{'y'} }; bless $self,$class; }; sub send{ my $s.. 阅读详情

相关推荐

[信号与系统]一阶与二阶连续时间系统和离散时间系统

定义:一阶连续时间系统由一阶线性常系数微分方程描述: dy(t)dt+ay(t)=bx(t) \frac{dy(t)}{dt} + a y(t) = b x(t) dtdy(t)​+ay(t)=bx(t)时间常数:时间常数 τ=1a\tau = \frac{1}{a}τ=a1​ 是系统响应速度的衡量指标。时间常数越小,系统响应越快。冲激响应:一阶系统的冲激响应是指数衰减或增长的形式。例如,对于一个单位冲激输入,响应为: h(t)=bae−at h(t) = \frac{b}{a} e^{-at} h(t)=

Andius的博客 2121

Perl 继承(inherit)

在这里直接放上一个例子:AdvancedFighter 继承了 Fighter Fighter.pm sub new { my $class = shift; my $self = { "NO" => shift, "HP" => shift, "attack" => shift, "defense" => shift, "speed" => shift, "d

weixin_45708589的博客 529

海康威视门禁考勤设备数据对接实战:从被动推送到主动拉取

本文深入探讨了海康威视门禁考勤设备数据对接的两种核心方案:HTTP推送与SDK主动拉取。文章对比了两种方式的适用场景、技术实现与优缺点,为开发者提供了从设备配置、代码编写到工程化部署的完整实战指南,帮助读者根据项目规模、网络环境及数据稳定性要求,做出最合适的技术选型。

weixin_29284657的博客 670

Perl中的类与继承

先定义一个Person类 package Person ; # package name must be same as file namesub new{ my $class = shift ; my ($name, $age) = @_ ; my $self = { "name" => $name, "age" => $age, ...

weixin_34236869的博客 160

基于OpenCV C++实现工业级形状模板匹配:仿Halcon SBM算法全解析

在计算机视觉和工业自动化领域,模板匹配是一项基础且关键的技术,用于在图像中定位已知目标。其核心原理是通过计算图像区域与预设模板之间的相似度来识别目标位置。传统的基于灰度值的匹配方法对光照变化敏感,鲁棒性不足。而基于边缘梯度方向的形状匹配技术,通过计算轮廓梯度方向的一致性进行相似度度量,从根本上提升了对光照变化的鲁棒性,并支持目标的旋转与缩放,技术价值显著。这项技术广泛应用于工业视觉检测、机器人引导、PCB定位等对精度和稳定性要求极高的场景。本文聚焦于使用开源OpenCV库,从底层仿照Halcon的Shape

weixin_33691817的博客 500

极空间NAS小白也能搞定的Gitea部署:Docker+MySQL避坑全记录

本文为极空间NAS用户提供了一份详尽的Gitea私有代码仓库部署指南。针对极空间ARM架构和图形化Docker管理的特殊性,文章重点讲解了如何通过Docker和MySQL容器进行部署,并提供了三种获取兼容镜像的实战策略,特别是利用第三方镜像站转录的方法,帮助小白用户成功搭建并初始化Gitea服务,实现私有Git托管。

weixin_28318011的博客 366

Perl面向对象(2):对象

本系列: Perl面向对象(1):从代码复用开始 Perl面向对象(2):对象 Perl面向对象(3):解构——对象销毁 第3篇依赖于第2篇,第2篇依赖于1篇。 已有的代码结构 现在有父类Animal,子类Horse,它们的代码分别如下: lib/Animal.pm中: #!/usr/bin/env perl use strict; use warnings; package Ani...

weixin_34336292的博客 375

abaqus 根据坐标施加载荷- Analytical Field 载荷映射

在一些类型的分析中,需要将按位置分布的载荷施加到结构上,比如流体分析导出了结构的气动载荷、或者温度载荷,需要将压强分布、温度分布载荷施加到固体上。这种分析可以使用abaqus中的Analytical Field实现。 1 例子 1.1 结构 一个100*100mm的面,面的载荷分布函数为p=(x2+y2)0.5/((20.5)*100) MPa,即(0, 0)的压强为0,(100, 100)的压强为1。 1.2 载荷 载荷函数:p=(x^2+y^2)^0.5/((2^0.5)*100) in exce.

shengyutou的博客 2万+

Perl 面向对象编程时 bless()函数的使用

1、说明 本程序演示了在Perl中如何进行面向对象编程:演示程序包含两个文件:person.pl 和 person.pm,把 person.pl 和 person.pm 放在当前目录下,运行"perl person.pl"即可以看到结果。person.pm定义了名为person

xinke453的专栏 5943

Cadence 批量一次性修改title 页码标题

本文介绍如何在Cadence软件中对DSN文件进行标题栏的批量编辑操作,包括选择编辑对象、使用快捷键打开属性面板以及如何修改标题、页码等关键信息。

tianpu2320959696的博客 975

ATT MTU 交换机制:提升 BLE 数据传输效率的关键

在低功耗蓝牙(BLE)技术的面试中,ATT MTU 交换机制始终是高频考点。无论是芯片厂商的固件开发岗,还是物联网设备的协议栈调试岗,面试官都爱通过这个知识点考察候选人对 BLE 数据传输底层逻辑的理解。本文将系统梳理核心考点,结合历年真题详解应答思路,轻松应对这类问题。​

byte轻骑兵的技术小窝 2411

Perl的面向对象方法

{ package LivingCreature; sub speak{ my $class = shift; my $gender = shift; print "a $gender $class goes "...

cu10025的博客 207

秋招突击——笔试整理——8/25——拼多多笔试整理

继续加油! 转变思维,有简单到复杂,由直观到抽象,这种贪心模拟的题目一直是这样的!

Blackoutdragon的博客 2400

Perl面向对象编程入门

因为项目原因,接触了一门新的语言—-Perl。初识之时,觉得它既像bash shell,又像C语言。因为有C/C++/Java以及shell基础,所以这门语言上水并没有很困难,但是它的面向对象还是给了我极其深刻的印象,因为它太“奇怪”了。即便是现在,我也不敢说理解了perl的面向对象编程,也仅仅是掌握了其基本的语法。本着学习分享的目的,今天,就通过一些简单代码来展示一下Perl的面向对象编程。在Ja

yangfang的博客 3577

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

perl 面向对象

https://www.runoob.com/perl/perl-object-oriented.html

weixin_47094487的博客 460

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Perl 面向对象

Perl面向对象编程摘要 Perl通过包(package)和引用实现面向对象编程(OOP),核心机制包括: 类与对象:使用package定义类,bless函数将引用与类关联创建对象 方法调用:通过->运算符调用方法 继承机制:借助@ISA数组实现继承关系 构造与析构:构造函数通常命名为new,析构函数为DESTROY 多态特性:支持方法重写,运行时动态绑定 Perl的OOP相比其他语言更灵活,需手动管理引用和内存,适合需要高度定制化的开发场景。

m0_57545130的博客 1223

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Perl的面向对象编程

一、模块简介  模块(module)就是Perl包(pachage)。Perl中的对象基于对包中数据项的引用。(引用见第x章引用)。  详见http://www.metronet.com的perlmod和perlobj。  在用其它语言进行面向对象编程时,先声明一个类然后创建该类的对象(实例),特定类所有对象的行为方式是相同的,由类方法确定,可以通过定义新类或从现存类继承来创建

EagleYIN417的专栏 1023

Perl 教学 面向对象编程

介绍如何使用Perl的面向对象编程(OOP)特性及如何构建对象,还包括继承、方法重载和数据封装等内容。 一、模块简介模块(module)就是Perl包(pachage)。Perl中的对象基于对包中数据项的引用。(引用见第x章引用。详见http://www.metronet.com/的perlmod和perlobj。 在用其它语言进行面向对象编程时,先声明一个类然后创建该类的对象(实例),...

weixin_33729196的博客 612

perl面向对象

Perl面向对象 转载:http://www.cnblogs.com/itech/archive/2012/08/21/2649580.html 首先让我们来看看有关 Perl 面向对象编程的三个基本定义:     1.  一个“对象”是指一个“有办法知道它是属于哪个类”的简单引用。(对象就是引用变量)     2.  一个“类”是指一个“有办法给属于它

frt007的专栏 568
上一篇: 面向对象的Perl 之一
下一篇: epoll简介 与 UDP server的实现
北雨南萍
北雨南萍 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 2665粉丝 453原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值