开发者

Why does this scheme get the error "Inconsistent hierarchy during C3 merge"?

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

And what--if anything--can I do about it?

  • Okay, I understand that Win32 inherits from Unix, but the dispatch is Win32 -> Unix and I want the Unix implementations as default until I override it and dispatch to the Win32 implementation my self.

  • I also understand that because File::Spec::x just passes around class names, that inheritance is not a huge issue, but I have to wonde开发者_JAVA百科r what would happen if I actually needed some classes to coordinate this way.


Conceptually, this makes no sense. You don't have something that's a unix path and a Windows path.

Practically, this makes no sense either. There is no function in ::Win32 that's not in ::Unix.

File::Spec already abuses inheritance, and you're taking it a leap further. Inheritance is not what you need here!

Anyway, this would be equivalent to what you have, minus the error:

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);
}


If what you want is to default to File::Spec::Unix in generally and specifically use File::Spec::Win32, you do not want to use multiple inheritance. File::Spec::Unix already inherits from File::Spec::Win32, so you've set up a (mostly) diamond inheritance which C3 does not want to resolve.

   Unix
   /  \
Win32  |
   |   |
  YourCode

You simply want to inherit from File::Spec::Unix and then use File::Spec::Win32 as desired.

package My::FileSpec;

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

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

If you want to get clever, you can eliminate the wrapper method.

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

Finally, you can put that into a loop to avoid repeating yourself.

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;
}

You can override isa to claim you're a File::Spec::Win32 as well as a File::Spec::Unix but that's not really true and would probably be more confusing than useful as your class only acts like Win32 for a handful of methods. Also, File::Spec has no object so it's practically not going to come up.

Overriding can is not necessary, it will return the correct code references.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜