有没有办法来覆盖sub a的class_1_1,并class_2_1用新的行为(两者相同的类)不增加重写的方法都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;  
Run Code Online (Sandbox Code Playgroud)
    一种量身定制的解决方案是为所需行为添加角色。
这是一个带有本机 OO 代码的示例,对角色使用独立的Role::Tiny
use warnings;
use strict;
use SomeClass;
my $obj = SomeClass->new;
$obj->a_method;
Run Code Online (Sandbox Code Playgroud)
班上 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;
Run Code Online (Sandbox Code Playgroud)
也可以将这个角色添加到其他类中,方法是向它们添加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;
Run Code Online (Sandbox Code Playgroud)
在Role::Tiny需要进行安装(没有依赖)。要替换在使用角色的类中定义的方法,我们需要一个方法修饰符 around,†由Class::Method::Modifiers 提供,因此这是一个额外的依赖项。
角色经常被比作继承,并声称提供了一个更好、更轻松的替代方案,因为继承通常“烘焙”到整个类层次结构等中。然而,继承通常专门化行为,而角色显然更灵活;他们添加或修改行为(或可以专门针对该问题)。我宁愿看到角色在继承和组合之间很好地匹配。
请注意,对于角色,我们可以拥有几乎等同于多重继承,几乎没有它令人生畏的(和令人生畏的)头痛。
上面的基本示例演示了Role::Tiny其自身的使用。但是使用Moose::Role或Moo:Role可以更好地利用角色与Moose或Moo框架。
我绝对建议研究这些框架。我坚信学习如何使用 Perl 的原生 OO 系统的价值,但是一旦有人掌握了这一点,不尝试Moose或Moo.
†在这个特定问题中,虽然要覆盖的方法是从另一个类继承的,但在这种情况下不需要修饰符。来自文档中的“角色构成”
如果一个方法已经在一个类上定义,该方法将不会从角色中组合。但是,由类继承的方法会被角色的同名方法覆盖。
所以在这个问题的情况下,通常在角色包中定义一个子就足够了
# In the package that defines roles (like 'AddedRoles' above)
sub a_method  { say "From an overriding role ", __PACKAGE__ } 
Run Code Online (Sandbox Code Playgroud)
当这个角色被一个继承 的类消耗时a_method,就像class_1_1在问题中一样,这个方法确实被这个方法覆盖了。
请注意,如果在类本身中定义了一个方法(未继承),那么定义为正常的角色将sub被悄悄忽略(它不会覆盖该方法,也不会发出警告等)。
另一方面,around在任何一种情况下都覆盖一个方法(在类中继承或定义),但不能添加根本不存在的方法(如果尝试会抛出异常)。