有没有办法用新的行为(两个类相同)覆盖 class_1_1
和 class_2_1
中的 sub a
而不添加被覆盖的class_1_1
和 class_2_1
的方法?
package class_0
sub a
sub b
1;
package class_1
use parent 'class_0'
sub b
1;
package class_2
use parent 'class_0'
sub b
1;
package class_1_1
use parent 'class_1'
1;
package class_2_1
use parent 'class_2'
1;
最佳答案
一个量身定制的解决方案是添加 role对于想要的行为。
这是一个带有 native OO 代码的示例,使用独立的 Role::Tiny对于角色
use warnings;
use strict;
use SomeClass;
my $obj = SomeClass->new;
$obj->a_method;
类SomeClass.pm
package SomeClass;
use warnings;
use strict;
use feature 'say';
use Role::Tiny::With; # To "consume" a role. Comes with Role::Tiny
# Consume roles from "AddedRoles.pm"
# That may add or require methods, or override the ones here
with 'AddedRoles';
sub new { bless { }, $_[0]] }
sub a_method { say "From ", __PACKAGE__ }
1;
这个角色也可以添加到其他类中,方法是添加 use
语句和行 with 'AddedRoles';
到它们,不管它们的继承关系如何。有关微调流程的方法,请参阅文档。
带有角色的包,AddedRoles.pm
package AddedRoles;
use feature 'say'; # we get strict and warnings from the package but not this
use Role::Tiny;
# Require that consumers implement methods; Add a method
#require method_1, method_2;
#sub added_method { say "Adding functionality to consumers" }
# Replace "a_method" in a consumer
around a_method => sub { say "From an overriding role ", __PACKAGE__ }
1;
Role::Tiny
需要安装(没有依赖)。
要替换在使用角色的类中定义的方法,我们需要一个 方法修饰符 around
,† 由 Class::Method::Modifiers 提供,所以这是一个额外的依赖。
角色经常被比作继承,并声称提供了一个更好、更轻便的替代方案,因为继承通常被“烘焙”到整个类层次结构等中。然而,继承通常专门行为,而角色很明显更灵活;他们添加或修改行为(或者可以专门针对此问题)。我宁愿看到角色在继承和组合之间很合适。
请注意,使用角色,我们可以拥有几乎等同于多重继承的功能,而几乎没有任何令人生畏的(和令人生畏的)令人头疼的问题。
上面的简单示例演示了 Role::Tiny
的使用。但是角色最好与 Moose
或 Moo
框架一起使用,使用 Moose::Role或 Moo:Role .
我绝对建议研究这些框架。我坚信学习如何使用 Perl 的 native OO 系统的值(value),但一旦掌握了这些,不尝试 Moose
或 Moo
.
† 在这个特定的问题中,虽然要覆盖的方法是从另一个类继承,在这种情况下不需要修饰符。来自 "Role Composition" in docs
If a method is already defined on a class, that method will not be composed in from the role. A method inherited by a class gets overridden by the role's method of the same name, though.
所以在这个问题的情况下,通常在角色包中定义一个子就足够了
# In the package that defines roles (like 'AddedRoles' above)
sub a_method { say "From an overriding role ", __PACKAGE__ }
当这个角色被一个继承 a_method
的类使用时,比如问题中的class_1_1
,这个方法确实被这个覆盖了一个。
请注意,如果一个方法在类中定义本身(未继承),那么定义为普通 sub
的角色会被忽略(它不会覆盖方法,它不会发出警告等)。
另一方面,around
在任何一种情况下都会覆盖一个方法(继承或在类中定义),但不能添加根本不存在的方法(如果那样的话会抛出异常已尝试)。
关于Perl 继承 - 子程序覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63585871/