【问题标题】:How do I create a Perl class?如何创建 Perl 类?
【发布时间】:2009-06-24 09:27:06
【问题描述】:

我正在编写 Perl 类来删除脚本中的冗余,而且由于 Perl 有很多方法可以创建类,所以我一直无法正确创建类。那么有人有一个类的最佳实践示例吗?

我最大的问题是,如果模块中不应该有全局变量,那么如何在模块中的 sub() 中使用变量?像 Java self->foo = 10;

基本上只是给我一个用 Java 或 C# 甚至 C++ 编写的类,然后用 Perl 编写相同的类。还有额外的点来展示如何正确地执行私有、受保护和公共类变量。我猜继承和接口会有所帮助。

【问题讨论】:

  • Perl 的 OO 功能充其量是有点缺乏...... :P 我会去看一个简单的 .pm 模块,看看它们是如何实现的

标签: perl oop


【解决方案1】:

创建 Perl 对象的典型方法是“祝福”一个 hashref。然后对象实例可以根据它自己的一组哈希键存储数据。

package SampleObject;

use strict;
use warnings;

sub new {
    my ($class, %args) = @_;
    return bless { %args }, $class;
}

sub sample_method {
    my ($self) = @_;
    print $self->{sample_data};
}

及用法:

my $obj = SampleObject->new( sample_data => 'hello world',
                             more_data   => 'blah blah blah' );
$obj->sample_method();

或者,可以添加访问器/修改器方法(请参阅 Class::Accessor、Class::Accessor::Chained 等,以便轻松设置这些方法) - 这些使验证数据和添加封装变得更容易(不强制执行)在 Perl 中,您必须确保您的代码不会绕过适当的访问器/修改器并直接访问受祝福的 hashref 中的数据)。

【讨论】:

  • 似乎是两个答案中最优雅的。
【解决方案2】:

嗯,Perl 很简单,但是我对其他语言很生疏,所以我会稍微更新一下。这是一个普通的 Perl 类:

#!/usr/bin/perl

package Person;

use strict;
use warnings;
use Carp;

sub new {
    my $class = shift;
    my $self  = { @_ };
    croak "bad arguments" unless defined $self->{firstname} and defined $self->{lastname}; 
    return bless $self, $class; #this is what makes a reference into an object
}

sub name {
    my $self = shift;
    return "$self->{firstname} $self->{lastname}";
}

#and here is some code that uses it
package main;

my $person = Person->new(firstname => "Chas.", lastname => "Owens");
print $person->name, "\n";

这是使用新 Moose 样式对象编写的同一个类:

#!/usr/bin/perl

package Person;

use Moose; #does use strict; use warnings; for you

has firstname => ( is => 'rw', isa => 'Str', required => 1 );
has lastname  => ( is => 'rw', isa => 'Str', required => 1 );

sub name {
    my $self = shift;
    return $self->firstname . " " . $self->lastname;
}

#and here is some code that uses it
package main;

my $person = Person->new(firstname => "Chas.", lastname => "Owens");
print $person->name, "\n";

MooseX::Declare 消除了对更多代码的需求,让事情看起来更美好:

#!/usr/bin/perl

use MooseX::Declare;

class Person {
    has firstname => ( is => 'rw', isa => 'Str', required => 1 );
    has lastname  => ( is => 'rw', isa => 'Str', required => 1 );

    method name {
            return $self->firstname . " " . $self->lastname;
    }
}

#and here is some code that uses it
package main;

my $person = Person->new(firstname => "Chas.", lastname => "Owens");
print $person->name, "\n";

快速说明,这两个类是我写的前两个 Moose 类。这里有一些非常生锈的 C++ 代码(不要在上面割伤自己,否则你需要打破伤风疫苗):

#include <stdio.h>
#include <string.h>

class Person {
    char* firstname;
    char* lastname;

    public:
    Person(char* first, char* last) {
        firstname = first;
        lastname  = last;
    }

    char* name(void) {
        int len = strlen(firstname) + strlen(lastname) + 1;
        char* name = new char[len];
        name[0] = '\0';
        strcat(name, firstname);
        strcat(name, " ");
        strcat(name, lastname);
        return name;
    }
};

int main(void) {
    Person* p    = new Person("Chas.", "Owens");
    char*   name = p->name();
    printf("%s\n", name);
    delete name;
    delete p;
    return 0;
}

【讨论】:

    【解决方案3】:

    查看Moose,它是 Perl 5 对象系统的扩展。

    以下内容将帮助您学习 Moose:

    【讨论】:

    • 我意识到这是一个流行的答案,但它实际上并没有告诉我如何让我自己的类类似于其他 OOP 语言。
    • 你是对的,相反,他给了你链接,告诉你如何做到这一点。当链接更好时,为什么要浪费字节从其他地方复制/粘贴。
    • @mpeters 因为链接已经过时了。如果该链接由于某种原因而失效,则该答案几乎毫无价值。这在 StackOverflow 常见问题解答中。
    【解决方案4】:

    除了 Moose,人们已经提到过……

    如果您只是在谈论类(所以,不是对象),您通常会创建具有文件范围内的词法变量的类数据,并且每个文件使用一个类。您创建访问器方法来处理它们。有多种方法可以解决这个问题。

    但是,听起来您需要从 Intermediate Perl 或 Damian Conway 的 Object Oriented Perl 之类的东西开始。任何人都需要花时间在 Stackoverflow 答案中重现所有这些内容,要解释的东西太多了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 2010-10-07
      • 1970-01-01
      • 2019-07-31
      • 2011-03-25
      • 2019-01-27
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多