名称冲突问题

假如在sum2.pm中使用require导入了一个代码文件sum1.pm:

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. require '/perlapp/sum1.pm';
  6. sub sum {
  7. say "sum2: sum()";
  8. }
  9. 1;

如果在sum1.pm中也有一个sum子程序:

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. sub sum {
  6. say "sum1: sum()";
  7. }
  8. 1;

那么在运行sum2.pm的时候,将警告子程序重新定义。因为sum2.pm首先编译好自己的sum(),然后在运行期间require导入文件时,又再次定义sum(),将进行覆盖操作:

  1. Subroutine sum redefined at /perlapp/sum1.pm.....

这样的名称冲突问题,通过声明包来解决。

定义包和访问包属性

要定义一个包,只需要加上关键字package即可。

  1. package PKG_NAME [ VERSION_NUM ];

上面的语句用于声明包,可以带上包版本号,例如package pkg1 0.01;

例如,在sum1.pm中:

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. package Sum1;
  6. sub sum {
  7. say "pkg:Sum1,sum()";
  8. }
  9. 1;

然后其它文件导入sum1.pm后,就可以使用包名::属性的方式访问sum1.pm中的属性,如子程序。

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. require '/perlapp/sum1.pm';
  6. sub sum {
  7. say "file: sum2,sum()";
  8. }
  9. sum(); # 访问本文件定义的sum子程序
  10. Sum1::sum(); # 访问包Sum1::sum子程序,括号不能少
  11. 1;

除了子程序,包中的其它非词法作用域的属性也能被访问,包括:标量、数组、hash、文件句柄。例如:

  1. $Sum1::name;
  2. @Sum1::arr;

每个文件都至少定义在一个包内,如果没有显式给定package指令,则这个包默认为main包。所以,访问本程序文件内自身属性的时候可以使用main:: + 属性的方式。例如在sum2.pm中:

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. require '/perlapp/sum1.pm';
  6. sub sum {
  7. say "file: sum2,sum()";
  8. }
  9. sum(); # 访问本文件定义的sum子程序
  10. main::sum(); # 等价于上一行直接访问sum()
  11. Sum1::sum(); # 访问包Sum1::sum子程序,括号不能少
  12. 1;

一个文件内多个包

一般来说,一个文件只会定义一个包。但允许一个文件定义通过包。

如下:

  1. package Pkg1;
  2. ...code here belong to Pkg1...
  3. package Pkg2;
  4. ...code here belong to Pkg2...

定义多个包时,从包1到包2中间的所有属性都属于包1。

例如,在sum1.pm中:

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.010;
  5. sub sum { # 位于默认的main包
  6. say "pkg:main,sum()";
  7. }
  8. package Sum1; # 第一个包
  9. sub sum { # 位于Sum1包
  10. say "pkg:Sum1,sum()";
  11. }
  12. sum(); # 访问的是Sum1包的sum()
  13. main::sum(); # 访问的是main包的sum()
  14. package Sum2; # 第二个包
  15. sub sum { # 位于Sum2包
  16. say "pkg:Sum2,sum()";
  17. }
  18. sum(); # 访问的是Sum2包的sum()
  19. Sum1::sum(); # 访问的是Sum1包的sum()
  20. main::sum(); # 访问的是main包的sum()
  21. 1;

有一些词语名称总是属于main包的: ARGV、ARGVOUT、ENV、INC、SIG、STDERR、STDIN 以及 STDOUT。有些带有特殊标点符号的名称(如$_,$2, $!),它们也全部属于main。

另外,词法变量是不能使用包名访问的,因为使用包访问的属性,都是"全局"属性。所以,要在代码块中访问全局属性,可以加上包名:

  1. package Sum1;
  2. out $var="1234";
  3. sub mysub {
  4. my $var;
  5. ...$var...; # 访问的是my $var
  6. $Sum1::var; # 访问的是Sum1包中的$var
  7. }

如果将一个包声明放进代码块,则出了代码块的域后就消失:

  1. package Sum1;
  2. {
  3. package main;
  4. sub sum {
  5. say "in main"
  6. }
  7. sum(); # 调用main中的sum
  8. } # 退出代码块,重新回到Sum1包
  9. sub sum {code} # 属于Sum1包的sum子程序

包代码块

从perl 5.12开始,支持包代码块:

  1. use v5.12;
  2. package pkg1 {
  3. ...
  4. }
  5. package pkg2 {
  6. ...
  7. }

包代码块相当于词法范围:

  1. package Navigation {
  2. my @homeport = (21.283, -157.842); # 属于包
  3. sub get_me_home {
  4. my @homeport; # 声明词法变量
  5. ... @homeport ... # 访问的是词法变量
  6. ... @Navigation::homeport ... # 访问的是包变量
  7. }
  8. ... @homeport ... # 访问的是包变量
  9. }

它等价于:

  1. {
  2. package Navigation;
  3. my @homeport = (21.283, -157.842); # 属于包
  4. sub get_me_home {
  5. my @homeport; # 声明词法变量
  6. ... @homeport ... # 访问的是词法变量
  7. ... @Navigation::homeport ... # 访问的是包变量
  8. }
  9. ... @homeport ... # refers to the package variable
  10. }

Perl包相关的更多相关文章

  1. GO 包相关

    1 包编译,eg: 引用pkgtest包 pkgtest包没有任何编译,项目直接导入引用,项目编译时实际是会编译pkgtest并在pkg\windows_386下生成pkgtest.a文件 再编译项目 ...

  2. 【转载】linux-查询rpm包相关安装、卸载脚本

        测试过程中,有时要测试开发自己打的rpm包,为了确认打包正确,需要查询rpm包相关安装.卸载脚本,可以使用命令:   [root@6 /]#rpm -q --scripts mysql pos ...

  3. Perl文件句柄相关常量变量

    文件句柄相关变量 对应的官方手册:http://perldoc.perl.org/perlvar.html#Variables-related-to-filehandles 默认情况下: $/:输入行 ...

  4. Perl包和模块(内容来自beginning perl)

    单文件版的perl程序只能用于构建较小的脚本程序.当代码规模较大时,应该遵循下面两条规则来构建程序.这样能将程序的各个部分按功能一个一个地细化,便于维护,也便于后续开发. 能复用的代码放进函数 能复用 ...

  5. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  6. R语言包相关命令

    R的包(package)通常有两种:1 binary package:这种包属于即得即用型(ready-to-use),但是依赖与平台,即Win和Linux平台下不同.2 Source package ...

  7. Android 网络编程 API笔记 - java.net 包相关 接口 api

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  8. rpm包相关操作

    1.查找已安装的rpm:rpm -qa|grep ewp2.卸载已安装的rpm: 先切换到虚拟机共享路径,执行卸载命令: rpm -e 已安装rpm包名称3.安装新rpm包:rpm -ivh(更新的话 ...

  9. Linux tar包相关命令

    tar [-j|-z][cv][-f 新建的文件名] filename... <==打包与压缩 tar [-j|-z][tv][-f 新建的文件名]   <==查看文件名 tar [-j| ...

随机推荐

  1. Python Flask学习笔记之模板

    Python Flask学习笔记之模板 Jinja2模板引擎 默认情况下,Flask在程序文件夹中的templates子文件夹中寻找模板.Flask提供的render_template函数把Jinja ...

  2. mac 电脑下svn

    mac点下使用的提交代码的方式是:eclipse + svn 的插件实现,总之中间遇到了很多的问题,不过还是都解决了. 前提是你已经安装了jdk. 安装的过程不再赘述直接上链接http://www.c ...

  3. window下载android 最新源码

    https://blog.csdn.net/jason0539/article/details/24010633 2017方法 ok https://www.cnblogs.com/zhangting ...

  4. linux vg lv pv

    = pv由物理卷或者分区组成   pv可以组成一个或者多个vg     vg可以分成多个lv 方便扩展 pvs vgs lvs 可以查看当前存在的pv vg lv 我的centos硬盘20g 使用了一 ...

  5. Shell条件测试和流程控制-4

  6. MySQL--自增列学习

    ##=====================================================================================## 在数据库表设计中会纠 ...

  7. Dubbo 源码分析 - 集群容错之 LoadBalance

    1.简介 LoadBalance 中文意思为负载均衡,它的职责是将网络请求,或者其他形式的负载"均摊"到不同的机器上.避免集群中部分服务器压力过大,而另一些服务器比较空闲的情况.通 ...

  8. 从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路

    本文原作者阮一峰,作者博客:ruanyifeng.com. 1.引言 HTTP 协议是最重要的互联网基础协议之一,它从最初的仅为浏览网页的目的进化到现在,已经是短连接通信的事实工业标准,最新版本 HT ...

  9. Javascript高级编程学习笔记(78)—— 表单(6)HTML约束验证API

    自动切换焦点 使用JS可以极大地提升表单的易用性 其中最常用的一种就是当用户填写完当前字段后焦点自动切换到下一个字段 以下方的HTML代码为例: <input type="text&q ...

  10. mysql命令行创建表,插入表数据

    create table t_hero( id int unsigned auto_increment primary key, name varchar(10) unique not null, a ...