简而言之,我尝试使用网络中每个实例的对象对网络拓扑进行建模。另外,我得到了一个高级经理类,负责管理这些对象和执行完整性检查。文件结构看起来像这样(我省略了大多数目标文件,因为它们的结构都相当相等):

Manager.pm
Constants.pm
Classes/
  +- Machine.pm
  +- Node.pm
  +- Object.pm
  +- Switch.pm

我来自OOP已有好几年了,我喜欢代码重用等。因此,我在thos对象之间设置了继承,继承树(在此示例中)如下所示:

Switch  -+-> Node -+-> Object
Machine -+

所有这些对象的结构如下:

package Switch;
use parent qw(Node);

sub buildFromXML {
  ...
}
sub new {
  ...
}

# additonal methods

现在有趣的部分:

问题1

如何在不静态输入名称的情况下确保正确加载所有这些对象?
潜在的问题是:如果我只是require "$_" foreach glob("./Classes/*");,则会收到许多“新的子例程重新定义于”错误。我还尝试了use parent qw(-norequire Object)Module::Find和其他一些@INC修改的各种组合,简而言之:它没有用。目前,我正在静态导入所有使用的类,它们会自动导入其父类。
所以,基本上,我要问的是:(perl-)正确的做法是什么?
和高级:能够创建更复杂的文件夹结构(因为将有很多对象)并且仍然具有继承+“自动加载”功能,将非常有帮助

问题2-解决了

如何“分享我的进口”?我使用了几个库(我自己的库,其中包含一些辅助函数,LibXMLScalar::Util等),我想在我的对象之间共享它们。 (其背后的原因是,我可能需要向所有对象添加另一个通用库,并且很有可能会超过100个对象-手动编辑所有对象并使用正则表达式/脚本进行理论上的工作很有趣,但理论上是可行的,但是似乎不是最干净的解决方案)
我试过的
  • 导入Manager.pm中的所有内容->在Manager程序包中工作-给我类似“未定义的子例程&Switch::trace称为”的错误
  • 在每个对象内创建一个include.pl文件并将do/require/use文件-给我相同的错误。
  • 还有一些我不记得
  • 的东西
    include.pl基本上看起来像这样:
    use lib_perl;
    use Scalar::Util qw(blessed);
    use XML::LibXML;
    use Data::Dumper;
    use Error::TryCatch;
    ...
    

    我再次问:正确的方法是什么?我是在使用正确的方法而只是执行失败,还是应该完全更改我的结构?
    没关系,为什么我当前的代码不能很好地工作,到目前为止,为这些问题提供正确,干净的方法就足够了:)

    编辑:完全忘记了perl版本-_-旁注:我无法升级perl,因为我需要使用5.8卡住的库:/

    C:\> perl -version
    This is perl, v5.8.8 built for MSWin32-x86-multi-thread
    (with 50 registered patches, see perl -V for more detail)
    
    Copyright 1987-2006, Larry Wall
    
    Binary build 820 [274739] provided by ActiveState http://www.ActiveState.com
    Built Jan 23 2007 15:57:46
    

    最佳答案

    这只是对问题2(共享进口)的部分回答。
    加载模块(通过use)有两件事:

  • 编译模块并将内容安装在命名空间层次结构(共享的)中。参见perldoc -f require
  • 调用每个已加载模块上的import子项。这会将一些子或常量等加载到调用者的 namespace 中。这是Exporter类在很大程度上隐藏起来的过程。这部分对于使用不带全名的潜艇等非常重要,例如max而不是List::Util::max。参见perldoc -f use

  • 让我们查看以下三个模块:ABUser
    {
       package A;
       use List::Util qw(max);
       # can use List::Util::max
       # can use max
    }
    {
       package User;
       # can use List::Util::max -> it is already loaded
       # cannot use max, this name is not defined in this namespace
    }
    
    软件包B定义了一个子load,该子eval将预定义的模块和子列表加载到调用者 namespace 中:
    {
       package B;
       sub load {
         my $package = (caller())[0]; # caller is a built-in, fetches package name
    
         eval qq{package $package;} . <<'FINIS' ;
           use List::Util qw(max);
           # add further modules here to load
           # you can place arbitrarily complex code in this eval string
           # to execute it in all modules that call this sub.
           # (e.g. testing and registering)
           # However, this is orthogonal to OOP.
    FINIS
    
         if ($@) {
           # Do error handling
         }
       }
    }
    
    User'd字符串中,我们暂时切换到调用程序包,然后加载指定的模块。这意味着load包代码现在如下所示:
    {
       package User;
       B::load();
       # can use List::Util::max
       # can use max
    }
    
    但是,您必须确保use B子本身已经加载。如果有疑问,请输入B::load()。在模块的其余部分编译之前,最好在BEGIN阶段执行eval:
    {
      package User;
      BEGIN {use B; B::load()}
      # ...
    }
    
    相当于
    {
      package User;
      use B;
      use List::Util qw(max);
      # ...
    }
    
    TIMTOWTDI。尽管我发现do编码的代码非常凌乱和危险,但这是我在这种情况下追求的方式(而不是Import::Into ing文件,该文件相似但有不同的副作用)。相比之下,手动混淆程序包 namespace 中的typeglobs真是令人头疼,复制粘贴模块名称列表就像回到甚至没有C的预处理器的时代。

    编辑: B
    …是一个CPAN模块,通过一个有趣的方法界面提供此功能。使用此模块,我们将通过以下方式重新定义eval包:
    {
      package B;
      use List::Util;   # you have to 'use' or 'require' this first, before using 'load'.
      use Import::Into; # has to be installed from CPAN first
      sub load {
        my $package = caller;
        List::Util->import::into($package, qw(max));
        # should work too: strict->import::into($package);
        # ...
      }
    }
    
    该模块从 View 中隐藏了所有脏活(ojit_code ing),并执行方法调用解析体操,以允许将编译指示导入其他 namespace 。

    关于perl - Perl:动态模块加载,对象继承和 “common helper files”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12419357/

    10-13 02:03