适当的Perl OO继承

时间:2015-10-06 19:51:29

标签: perl oop inheritance

我试图在我们的代码库中创建一个自定义模块的子类。我们将模块放在我们所有文件中包含的目录中。所以我们从

开始
NSLog(@"layoutSubviews: mediaItem=%p image=%p size=%@",
    self.mediaItem, self.mediaItem.image,
    NSStringFromCGSize(self.mediaItem.image.size));

接下来,我的父模块位于use Env; use lib "$ENV{OurKey}/RootLib"; # All of our modules are here ,其代码长期存在,所以我宁愿不改变其中任何一个,而是让孩子能够继承它原样。

RootLib/Dir1/Parent.pm

此时,我有点迷失,因为我已经看到了许多不同的方法来定义子构造函数,但没有一个对我有用。这就是我所拥有的,但它不起作用,因为在子包中找不到应该从父项继承的子程序。子包位于package Parent; use strict; use warnings; use Env; use lib "$ENV{OurKey}/RootLib"; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; # Some other stuff bless ($self, $class); return $self; }

RootLib/Dir1/Dir2/Child.pm

然后,在我的test.pl文件中,我有

package Child;
use strict;
use warnings;
use vars qw(@ISA);
use Env;
use lib "$ENV{OurKey}/RootLib";

require Dir1::Parent;
push @ISA, 'Dir1::Parent';

sub new {
    # This constructor is clearly incorrect, please help
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self = Parent::new($class);

    bless ($self, $class);
    return $self;
}

2 个答案:

答案 0 :(得分:2)

父类声明它在package Parent中(即使包含它的文件是Dir1/Parent.pm),因此孩子的@ISA应该只包括Parent }。

或者您可以通过一些额外的use lib ...语句解决您不幸的目录结构。

package Child;
use lib "$ENV{OurKey}/RootLib/Dir1";
require Parent;      # found in $OurKey/RootLib/Dir1/Parent.pm
our @ISA = ('Parent');
...

# test.pl
use lib "$ENV{OurKey}/RootLib/Dir1/Dir2";
use Child;           # found in $OurKey/RootLib/Dir1/Dir2/Child.pm
...

答案 1 :(得分:0)

准父类有package Parent;,但您有@ISA = 'Dir1::Parent';。那些不匹配,这就是无法找到方法的原因。 (那,以及你实际上没有在任何地方定义方法的事实!)

文件名,package语句中的名称,use语句中的名称以及@ISA中的名称都必须匹配。

以下是两种可能的解决方案。

如果类名为Dir1::ParentDir1::Dir2::Child

use lib "$ENV{OurKey}/RootLib";

use Dir1::Parent      qw( );
use Dir1::Dir2::Child qw( );

(请注意use Env已删除,因为它未被使用。)

(.../RootLib/)Dir1/Parent.pm

package Dir1::Parent;          # Must match the file name.
use strict;
use warnings;

...

(.../RootLib/)Dir1/Dir2/Child.pm

package Dir1::Dir2::Child;     # Must match the file name.
use strict;
use warnings;

use Dir1::Parent qw( );        # Must match the file name
our @ISA = 'Dir1::Parent';     #   and the package name.
   -or-
use parent 'Dir1::Parent';     # This can replace the other two lines.

...

如果类名为ParentChild

不要在模块中修改@INC(例如通过use lib)。您的脚本应包含以下内容:

use lib
   "$ENV{OurKey}/RootLib/Dir1",
   "$ENV{OurKey}/RootLib/Dir1/Dir2";

use Parent qw( );
use Child  qw( );

(注意,在另一个库目录中有一个库目录真的很奇怪!)

(.../RootLib/Dir1/)Parent.pm

package Parent;                # Must match the file name.
use strict;
use warnings;

...

(.../RootLib/Dir1/Dir2/)Child.pm

package Child;                 # Must match the file name.
use strict;
use warnings;

use Parent qw( );              # Must match the file name
our @ISA = 'Parent';           #    and the package name.
   -or-
use parent 'Parent';           # This can replace the other two lines.

...

至于构造函数,

父:

sub new {
    my $class = shift;                # That proto thing is a bad practice.
    my $self = bless({}, $class);     # Don't need two lines to do this.

    # ...

    return $self;
}

子:

sub new {
    my $class = shift;                # That proto thing is a bad practice.
    my $self = $class::SUPER->new();  # Don't need two lines to do this.
                                      # If you don't need to do anything here,
    # ...                             #   you can just inherit the parent's new
                                      #   by removing this sub entirely.
    return $self;
}