为什么这个方案得到错误“C3合并期间不一致的层次结构”?

时间:2011-04-26 21:09:32

标签: perl multiple-inheritance method-resolution-order

use parent qw<File::Spec::Unix File::Spec::Win32>;

什么 - 如果有的话 - 我可以做些什么呢?

  • 好的,我知道Win32继承自Unix,但调度是Win32 -> Unix,我希望Unix实现为默认值,直到我覆盖它为止发送到我自己的Win32实现。

  • 我也明白,因为File::Spec::x只是传递类名,所以继承不是一个大问题,但我不得不想知道如果我真的需要一些类来协调这种方式会发生什么。

2 个答案:

答案 0 :(得分:3)

从概念上讲,这没有任何意义。你没有unix路径和Windows路径。

实际上,这也没有任何意义。 :: Win32中没有函数不在:: Unix。

File :: Spec已经滥用继承,你进一步实现了它的飞跃。继承不是你需要的!

无论如何,这相当于你所拥有的,减去错误:

use parent qw( File::Spec::Unix );
use File::Spec::Win32 qw( ); 

sub isa {
    my ($self, $class) = @_;
    return $class eq 'File::Spec::Win32' || $self->SUPER::isa($class);
}

答案 1 :(得分:1)

如果您想要的是默认使用File :: Spec :: Unix,并且特别使用File :: Spec :: Win32,则不希望使用多重继承。 File :: Spec :: Unix已经从File :: Spec :: Win32继承,所以你设置了一个(大部分)钻石继承,C3不想解析。

   Unix
   /  \
Win32  |
   |   |
  YourCode

您只想继承File :: Spec :: Unix,然后根据需要使用File :: Spec :: Win32。

package My::FileSpec;

use parent qw(File::Spec::Unix);
require File::Spec::Win32;

sub devnull {
    my $class = shift;
    return $class->File::Spec::Win32(@_);
}

如果你想变得聪明,你可以取消包装方法。

*devnull = File::Spec::Win32->can("devnull");

最后,您可以将其放入循环中以避免重复自己。

my @Win32_Methods = qw(devnull tmpdir);
for my $method (@Win32_Methods) {
    my $code = File::Spec::Win32->can($method);
    die "File::Spec::Win32->$method does not exist" unless $code;

    no strict 'refs';
    *{$method} = $code;
}

你可以覆盖isa声称你是一个File :: Spec :: Win32以及一个File :: Spec :: Unix但是这不是真的,可能会比你有用更麻烦对于少数几种方法,类只对Win32起作用。此外,File :: Spec没有任何对象,所以实际上它不会出现。

不需要覆盖can,它将返回正确的代码引用。