C++-like usage of Moose with Perl for OOP

2019-03-20 14:47发布

问题:

I've been playing around with Moose, getting a feel for it. I'd like an example of pure virtual functions like in C++ but in Moose parlance (specifically in a C++-looking way). I know that even with Moose imposing a stricter model than normal Perl, there's still more than one way to do what I'm asking (via method modifiers or SUPER:: calls). That is why I'm asking specifically for an implementation resembling C++ as much as possible. As for the "why?" of this restriction? Mostly curiosity, but also planning to port some C++ code to Perl with Moose in a way that C++-centric people could mostly identify with.

回答1:

I can think of this way using roles instead of subclassing:

{
    package AbstractRole;
    use Moose::Role;
    requires 'stuff';  
}

{
    package Real;
    use Moose;
    with 'AbstractRole';
}

This will give a compilation error because Real doesn't have stuff defined.

Adding stuff method to Real will now make it work:

{
    package Real;
    use Moose;
    with 'AbstractRole';

    sub stuff { print "Using child function!\n" }
}


回答2:

You might also want to take a look at Jesse Luehrs' MooseX::ABC. It seems very similar to some of the implementations here. From the synopsis:

package Shape;
use Moose;
use MooseX::ABC;

requires 'draw';

package Circle;
use Moose;
extends 'Shape';

sub draw {
    # stuff
}

my $shape = Shape->new; # dies
my $circle = Circle->new; # succeeds

package Square;
use Moose;
extends 'Shape'; # dies, since draw is unimplemented

I know that Jesse is a C++ programmer during the day.



回答3:

It appears I can't do exactly what I want with Moose, but I can come very close with Roles. Here is the information from the Moose manual entry for Roles:

Roles Versus Abstract Base Classes

If you are familiar with the concept of abstract base classes in other languages, you may be tempted to use roles in the same way.

You can define an "interface-only" role, one that contains just a list of required methods.

However, any class which consumes this role must implement all of the required methods, either directly or through inheritance from a parent. You cannot delay the method requirement check so that they can be implemented by future subclasses.

Because the role defines the required methods directly, adding a base class to the mix would not achieve anything. We recommend that you simply consume the interface role in each class which implements that interface.



回答4:

Here is was my attempt (without Roles, for information on Roles see the other answers):

package Abstract;
use Moose;

sub stuff;

package Real;
use Moose;
extends 'Abstract';

override 'stuff' => sub { print "Using child function!\n"; }


标签: c++ perl oop moose