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 fromUnix
, but the dispatch isWin32 -> Unix
and I want theUnix
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.
精彩评论