Reputation: 21
How I can emulate in my Perl code things like Ruby's "include"/"extend" mechanism?
Let's take for example the following code in Ruby:
module ActiveRecord
class Base
class << self
#...
end
#...
end
Base.class_eval do
include ActiveRecord::Persistence
extend ActiveModel::Naming
extend QueryCache::ClassMethods
extend ActiveSupport::Benchmarkable
extend ActiveSupport::DescendantsTracker
include ActiveModel::Conversion
include Validations
extend CounterCache
include Locking::Optimistic, Locking::Pessimistic
include AttributeMethods
...
end
end
It leads me to ask this question, because I can't find any clear idea during several days of researching. So, maybe there exists some good way to organize it in Perl?
Upvotes: 2
Views: 299
Reputation: 22560
A literal translation of this code to Perl/Moose would (kinda) look like this:
package ActiveRecord::Base;
use Moose;
use namespace::autoclean;
with qw(
ActiveRecord::Persistence
ActiveModel::Naming
QueryCache::ClassMethods
ActiveSupport::Benchmarkable
ActiveSupport::DescendantsTracker
ActiveModel::Conversion
Validations
CounterCache
Locking::Optimistic
Locking::Pessimistic
AttributeMethods
);
__PACKAGE__->meta->make_immutable;
1;
Above uses Moose Roles which are equivalent to Ruby's mixins.
In Ruby include
is for mixing in instance methods whereas extend
is for class mixins. In Perl all methods can be called by class or instance so roles are added using with
.
Upvotes: 1
Reputation: 118128
Here is a small example:
#!/usr/bin/env perl
use 5.014;
package My::Quoted {
use Role::Tiny;
sub quoted_name {
my $self = shift;
return sprintf q{"%s"}, $self->name;
}
}
package My::One {
use Moo;
has name => (is => 'ro');
sub greet {
my $self = shift;
return sprintf 'Hello %s', $self->name;
}
}
package My::Two {
use Moo;
extends 'My::One';
with 'My::Quoted';
sub greet {
my $self = shift;
return sprintf 'Merhaba %s', $self->quoted_name;
}
}
package main {
run('Perl');
sub run {
my $name = shift;
my $x = My::Two->new({name => $name});
my $y = My::One->new({name => $name});
say $_->greet for $x, $y;
}
}
Output:
Merhaba "Perl" Hello Perl
Upvotes: 3
Reputation: 5171
That looks like traits/mixins vs inheritance, both done at runtime.
The traits/mixins parts are covered by a Perl6 concept called a Role.
How to implement in Perl 5? Look no further than Moose (see also the perldoc for Moose)
I believe it started as a proving ground for the OO/meta language support features headed for Perl 6, but in Perl 5. Now it has taken on a life of its own and a great many CPAN packages have dependencies on Moose.
Moose implements a wide variety of Object Oriented language constructs (from a few different OO paradigms) and is very extensible.
An explanation of the concepts in Moose and how they map to constructs in other languages can be found in the Concepts section of the Moose manual
Additionally, the Moose
and MooseX
namespaces on CPAN are chock full of complimentary (or experimental) packages to add support for even more OO constructs.
Upvotes: 7