为什么此方案会出现错误“C3 合并期间层次结构不一致”?

发布于 2024-11-03 18:55:59 字数 378 浏览 6 评论 0原文

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

如果有的话,我能做些什么呢?

  • 好的,我知道 Win32 继承自 Unix,但调度是 Win32 -> Unix 并且我希望将 Unix 实现作为默认值,直到我重写它并分派给我自己的 Win32 实现。

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

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 wonder what would happen if I actually needed some classes to coordinate this way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一身骄傲 2024-11-10 18:55:59

从概念上讲,这是没有意义的。您没有 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);
}

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);
}
家住魔仙堡 2024-11-10 18:55:59

如果您想要的是在一般和专门使用 File::Spec::Win32 时默认为 File::Spec::Unix,则您不想使用多重继承。 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,它将返回正确的代码引用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文