Perl - 有没有办法导入一个类及其所有子类?

sna*_*pan 3 perl

在java中,有一种方法可以在一行中导入一个类及其所有子类:

import java.utils.* 
Run Code Online (Sandbox Code Playgroud)

在Perl中,我发现我只能导入特定的类:

use Perl::Utils::Folder;
use Perl::Utils::Classes qw(new run_class);
Run Code Online (Sandbox Code Playgroud)

是否有类似java的方式导入属于树结构的所有东西,只有Perl?

Zac*_*c B 5

不,没有办法轻松做你想做的事.

您可以在PERL库的文件系统和您遇到的use每个.pm文件中走相关路径(Module::Find正如@DanielBöhmer所建议的那样),但这可能会遗漏一些事情:

  • 以有趣的方式/在运行时声明的包.
  • 每个模块文件多个包.
  • 其他我没有想到的情况.

这也是一个坏主意,原因如下:

  • 您在问题中提到了"类",而不仅仅是包.Perl包和子包不一定代表类/可实例化的面向对象的代码.如果您以编程方式生成层次结构中所有包的列表,然后调用$packagename->new()每个包,则可能会出现语法错误,如果其中一个包只是一个函数库.
  • 包和子包通常不是直接相关的,由同一个人开发,或用于类似的东西.仅仅因为包开始Net::并不意味着它将遵循其他 - Net::前缀包期望的标准约定.例如,File::FindFile::Tail共享一个前缀,但彼此之间几乎没有关系; 前缀是共同的,因为两个实用程序都以文件作为目标.
  • 包做很多事情BEGIN/ INIT时,他们正在编译/等时间.他们中的一些人(遗憾地)做了不同的事情,这取决于他们use相对于其他模块顺序.模块开发人员解决这个问题的方法是"不要那样做",但对于模块用户来说,它是" use谨慎的,只有在需要时".
  • 它使您需要的许多潜在导出符号混乱您的本地命名空间(有条件地导入符号,您必须使用import您在示例中所做的参数;没有编程方式来定义"符号I"感兴趣的是",因为Perl在编译时没有那种静态分析......至少对于很多调用样式而言都没有."
  • 它通过编译您可能不一定需要的东西来减慢程序的启动时间.这在项目的早期阶段似乎并不重要,但对于较大的项目,当你启动Apache(或启动主脚本,或者其他任何东西)时,你很容易就会遇到超过一千个CPAN模块的情况. ),你的应用程序需要一分多钟才能开始.

我有一种预感,你正试图减少样板(如:你的所有模块都use在顶部有一大块语句,而且到处都是重复的).有几种方法可以做到这一点,从以下开始:

  • 不要:根据需要导入每个模块中的内容,并且如果您正在调用尚未导入的功能,请尽早使用strict/ warnings和大量测试.
  • 您还可以创建自己的Exporter子类,use这些子类是您的所有标准模块,并将您经常使用的函数添加到其中@EXPORTS(或者@EXPORTS将它们自己拼接,或者使用Exporter子子类或其他东西).
  • 考虑您的代码,以便依赖多个导入模块的部分存在于单个实用程序模块中,然后导入它.
  • 考虑您的代码,以便依赖导入模块的部分存在于父类中,并通过子类(或SUPER)的实例寻址其方法,因此您的子类不必显式包含导入,例如$instance->method_that_calls_an_imported_function_in_the_parent();

此外,另外,package.*在Java中使用导入是有争议的,并且在Perl中使用导入具有许多相同的缺点.


Dav*_* W. 5

在Perl中, Foo::Bar::Foo可能不是一个子类Foo::Bar.也不保证子类模块甚至具有相同的类前缀.IO::File是一个子类,IO::Handle而不是IO一个模块.

还有一种简单的方法可以告诉Perl模块是另一个Perl模块的子类.有(至少)三种方法来声明子类与类的关系:

  • use parent
  • use base
  • @ISA包变量

它可以使用@INC查找所有的模块,再看看源看看use parent,use base@ISA声明,并建立一个Perl类基质,然后再通过矩阵加载你需要的类.这可能是缓慢而繁琐的,甚至不包括基于穆斯的课程.

你问的是错误的问题.你问"查找特定类的所有子类. ".这将包括你可能甚至不感兴趣的类.我知道(例如LWP)可能有几十个不同的类和子类包含你甚至不感兴趣的东西.

您应该问的是" 我需要做什么? ",然后找到满足您需求的课程.如果这些类恰好是特定父类的子类,则这些子类将加载所需的类.

我们在这里进行Java编程,其中一个标准是不在我们的import语句中使用星号.这被认为是草率的编程.如果你需要一个特定的类,你应该声明它而不是简单地声明一个超类.我们的许多报告工具都存在import语句中星号声明的问题.

有一个Module::Find模块,但我不确定它是如何工作的.我相信它只是假设子类与超类在同一模块层次结构中,但这在Perl中远非如此.