Perl是多态的值得吗?

sli*_*oad 0 oop polymorphism perl

在Perl中似乎有很多方法可以做多态,但他们都对我感到"hacky".我对Perl有点新意,所以我可能只是错误地解释它,但我发现大多数例子都会使你的代码难以辨认并且引起争议.

假设您有一个窗口小部件类,其中包含所有窗口小部件所需的一些数据和方法.还有一些小部件类型(即日历,日程安排等).并且他们需要彼此通信(通过父容器类).

使用命名空间并使小部件成为原型值得吗?
我应该在实例化时为每个窗口小部件提供对象(其中一种类型)的引用吗?
只是忘记作为对象的类型,并使widget成为一个大类,其中每个实例只根据设置的类型使用几个方法.别的什么?

我来自C/C++背景,我发现很难决定Perl编程模型.

此外,我没有强大的类型安全或私人成员要求.该项目是一个中等规模的Web应用程序,有几个开发人员和其他项目的可移植性不是一个优先事项.尽管如此,易于扩展而无需破译Perl黑客将是有用的.

tob*_*ink 6

"现代Perl"方法可能被定义Widget为一个角色.可以认为角色类似于mixin,接口或抽象基类.使用Moose :: Role或其中一个更轻量级的替代品(Moo :: Role,Role :: Tiny)来做这件事.

{
   package Widget;
   use Moo::Role;

   sub some_common_method {
      my $self = shift;
      ...;
   }

   sub another_common_method {
      my $self = shift;
      ...;
   }

   # Here we're indicating that all Widgets must
   # have a method called yet_another_common_method,
   # but we're not defining how that method should
   # be implemented.
   requires "yet_another_common_method";
}
Run Code Online (Sandbox Code Playgroud)

现在您可以创建一个组成该角色的类:

{
   package Calendar;
   use Moo;
   with "Widget";

   # Here's a member variable.
   has year => (is => "ro", required => 1);

   # Widget requires us to implement this.
   sub yet_another_common_method {
      my $self = shift;
      ...;
   }

   # We can override Widget's implementation
   # of this method.
   sub some_common_method {
      my $self = shift;
      ...;
   }

   # We can install hooks ("method modifiers")
   # to Widget's methods.
   before another_common_method => sub {
      my $self = shift;
      print STDERR "Calendar ", $self->year, ": another_common_method() was called.\n";
   };
}
Run Code Online (Sandbox Code Playgroud)

而另一个:

{
   package Schedule;
   use Moo;
   with "Widget", "Editable";

   sub yet_another_common_method {
      my $self = shift;
      ...;
   }
}
Run Code Online (Sandbox Code Playgroud)

并使用类:

my $calendar = Calendar->new( year => 2014 );
my $schedule = Schedule->new;

my @widgets = ($calendar, $schedule);

for (@widgets) {
   $_->some_common_method if $_->does('Widget');
}
Run Code Online (Sandbox Code Playgroud)