2

如何在我的 Perl 代码中模拟 Ruby 的“包含”/“扩展”机制?

让我们以 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

这导致我问这个问题,因为在几天的研究中我找不到任何明确的想法。那么,也许存在一些在 Perl 中组织它的好方法?

4

3 回答 3

7

这看起来像traits/mixins继承,两者都是在运行时完成的。

特征/混合部分被称为角色的 Perl6 概念所涵盖。

如何在 Perl 5 中实现?看看Moose就知道了(另请参阅 Moose 的perldoc

我相信它开始是作为面向 Perl 6 的 OO/元语言支持特性的试验场,但在 Perl 5 中。现在它已经有了自己的生命,许多 CPAN 包都依赖于 Moose。

Moose 实现了多种面向对象的语言结构(来自几个不同的 OO 范例),并且具有很强的可扩展性。

Moose 中的概念以及它们如何映射到其他语言的结构的解释可以在Moose 手册的概念部分找到

此外,CPAN 上的MooseMooseX命名空间充满了免费的(或实验性的)包,以增加对更多 OO 结构的支持。

于 2012-04-08T07:54:53.120 回答
3

这是一个小例子:

#!/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;
    }
}

输出:

梅尔哈巴“Perl”
你好 Perl
于 2012-04-08T14:02:13.190 回答
1

将此代码直译为Perl/Moose 会(有点)如下所示:

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;

上面使用了相当于 Ruby 的 mixin 的Moose Roles 。

在 Rubyinclude中用于混合实例方法,而extend用于类混合。在 Perl 中,所有方法都可以由类或实例调用,因此使用with.

于 2012-10-19T14:40:32.853 回答