gpt4 book ai didi

perl - 多重继承 - 选择了错误的重载

转载 作者:行者123 更新时间:2023-12-02 18:26:17 25 4
gpt4 key购买 nike

我正在尝试多重继承,并且想在不使用像 Moose 这样的包来解决幕后问题的情况下掌握它。

我有两个基类,LeftRight,在一个“ splinter 的”菱形中:

Left  Right
\ /
Multi

它们都为 "" 实现了一个重载。当在任何基类中调用名为 perform 的方法时,这些方法应该使用此重载来打印对象的该部分的表示。 Multi 如此实现 perform:

sub perform {
my $self = shift;
$self->Left::perform;
$self->Right::perform;
}

发生的情况是两个基类 perform 方法都按预期调用,但是当这些方法调用任何其他方法(如 "" 重载)时,它'将永远是 Left 中的那个。但是,如果 Right 的实例是单独创建的(不是作为 Multi 的一部分),它将调用正确的方法。

  • 我想知道在这种情况下如何让一个方法选择它自己的包的方法而不是它最左边的兄弟基类的方法?

这是我尝试过的(在 v5.26.1 和 v5.32.1 中):

#!/usr/bin/perl

use strict;
use warnings;

package Left; #----------------------------------------------------------------

sub new {
my ($class, @args) = @_;
my $self = bless {}, $class;
return $self->_init(@args);
}

sub _init {
my $self = shift;
$self->{_leftval} = shift;
return $self;
}

sub value { shift->{_leftval}; }

use overload '""' => sub {
my $self = shift;
'Left(' . $self->value . ')';
};

sub perform {
my $self = shift;
print '# LEFT ' . $self . "\n";
}

package Right; #---------------------------------------------------------------

sub new {
my ($class, @args) = @_;
my $self = bless {}, $class;
return $self->_init(@args);
}

sub _init {
my $self = shift;
$self->{_rightval} = shift;
return $self;
}

sub value { shift->{_rightval}; }

use overload '""' => sub {
my $self = shift;
'Right(' . $self->value . ')';
};

sub perform {
my $self = shift;
print '# RIGHT ' . $self . "\n";
}

package Multi; #---------------------------------------------------------------
use parent -norequire, 'Left', 'Right' ;

sub new {
my ($class, @args) = @_;
my $self = bless {}, $class;
return $self->_init(@args);
}

sub _init {
my $self = shift;
$self->Left::_init(shift);
$self->Right::_init(shift);
return $self;
}

sub perform {
my $self = shift;
$self->Left::perform;
$self->Right::perform;
}

package main; #----------------------------------------------------------------

my $l = Left->new("a Left");
my $r = Right->new("a Right");
my $m = Multi->new("lEfT", "rIgHt");

$l->perform;
$r->perform;
print "---- and now a Multi ----\n";
$m->perform;

预期输出:

# LEFT Left(a Left)
# RIGHT Right(a Right)
---- and now a Multi ----
# LEFT Left(lEfT)
# RIGHT Right(rIgHt)

实际输出(注意最后一行):

# LEFT Left(a Left)
# RIGHT Right(a Right)
---- and now a Multi ----
# LEFT Left(lEfT)
# RIGHT Left(lEfT)

最佳答案

虚方法是根据对象的类来解析的,而不是调用者的命名空间/包/类。

在 Perl 中,方法是否为虚方法不是固有属性。这取决于它的调用方式。

$o->method   # Virtual method

避免这种情况需要指定类

$o->Class::method

您不需要虚拟方法调用,因此您需要更改调用方法的方式。

package Left;

use overload '""' => \&to_string;

sub to_string {
my $self = shift;
'Left(' . $self->value . ')';
}

sub perform {
my $self = shift;
print '# LEFT ' . $self->Left::to_string() . "\n";
}

除了这一切都是错误的。如果这是一种方法,这将是有道理的。但我们正在谈论每一种方法。这是红旗的空袭警报。

我们在这里想要的是组合,而不是继承。 Multi IS A Left 和 IS A Right 是不正确的。相反,Multi 有左有右。

package Multi; #---------------------------------------------------------------
use parent -norequire, 'Left', 'Right' ;

sub new {
my ($class, @args) = @_;
my $self = bless {}, $class;
return $self->_init(@args);
}

sub _init {
my $self = shift;
$self->{ left } = Left ->new(shift);
$self->{ right } = Right->new(shift);
return $self;
}

sub perform {
my $self = shift;
$self->{ left }->perform;
$self->{ right }->perform;
}

关于perl - 多重继承 - 选择了错误的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70109979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com