为了祝福或不祝福,这是我的问题!

时间:2010-08-11 03:07:16

标签: perl oop class bless

来自新手用户的第一篇帖子。我谷歌的每一个问题似乎都把我带到了这里,我总能得到一个很好的答案,我正在寻找的东西;所以当我开始思考在Perl中使用祝福时,这是我的第一站。

我刚刚进入Perl的OOP,就在今天阅读帖子,询问保佑的作用。我现在明白它会引用一个标量/散列/数组到一个对象,“附加”它,如果你愿意的话。

在我在Perl中看到的大多数类的例子中,它们似乎没有我以前在其他语言中看到的属性...

{ package Person;
    my $property = "This is what I'm talking about :)";

    sub new { ... }
    ...
}

所以,我创建了一个带有属性的愚蠢类,看看会发生什么。我立刻给了物业'NIL'的价值,然后'Not Nil!'在构造函数中。使用方法LIST,我能够打印属性,正如我所料,它打印出'Not Nil!'

我的问题是,如果属性的工作方式与我预期的相同(在体内声明)那么为什么要使用保佑呢?当您可以简单地创建标量/散列/数组作为属性,或者创建您想要作为属性的任何引用时,具有该引用的额外好处是什么?

我希望我用Perl解释了我要问的问题,非常绿色:)

4 个答案:

答案 0 :(得分:11)

嗯,这不是你在Perl中创建类的方法。

您的$property变量在包范围内定义。因此,每个类只有一个副本,而不是每个对象都有自己的副本。

有人可能会使用基于哈希的对象来实现这样一个类,如下所示:

#!/usr/bin/perl

package Person;

use strict; use warnings;

sub new {
    my $class = shift;
    my $self = {};
    bless $self => $class;

    my ($arg) = @_;
    for my $property ( qw( message ) ) {
        if ( exists $arg->{$property} ) {
            $self->$property($arg->{$property});
        }
    }
    return $self;
}

sub message {
    my $self = shift;
    return $self->{message} unless @_;
    my ($msg) = @_;
    $self->{message} = $msg;
}

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";

现在,这很快就会变得乏味。因此,有一些模块可以帮助您处理这个问题,并帮助您以可靠的继承方式定义类。

Class::Accessor就是这样一个实用程序模块。

对于启动时间不是问题的程序,您应该考虑Moose。使用Moose,您可以将上面的内容写成:

#!/usr/bin/perl

package Person;

use Moose;

has 'message' => (is => 'rw', isa => 'Str');

__PACKAGE__->meta->make_immutable;
no Moose;

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";

您应该阅读perldoc perltootMoose::Manual::Unsweetened了解标准的做事方式。

答案 1 :(得分:8)

在这种情况下,您对$ property所做的事情在“Person”包的范围内被声明为变量。您在包内部(或使用$ Person :: property外部)更改它,并且引用它的任何对象都将看到更新的变量,因此它的行为很像“静态属性(Java)”而没有任何真正的“私人”范围。按照惯例,Perl中的隐藏内容(“私有”或“受保护”)以下划线为前缀,但当然不会强制执行。

正如您所指出的,您实际上并没有使用“package”关键字创建一个新类;你可以使用没有OOP的“包”。这只是创建一个单独的“命名空间”。

“祝福”变量的优势,几乎总是来自我所见过的哈希引用,就是你可以拥有方法,就像任何其他OOP语言一样。只记得保佑你在新的{}子程序中返回的任何内容(“new”实际上不是一个保留字;只是一个约定)。当您在“对象”(像hashref这样的祝福数据结构)上调用方法时,该方法的第一个参数就是数据结构本身。所以,如果你有一个名为$ MyObject的hashref,这是有福AwesomeClass,并且定义在AwesomeClass的方法称为doSomethingAwesome,它需要接受一个变量,你必须“换挡” @_(这是参数列表子例程,或使用$ _ [0])来访问$ myobject hashref。 Python做了类似的事情,所有语言都以某种方式将对象引用传递给方法。 (许多中的“this”关键字,另请参阅“thiscall”调用约定)

注意:我在我的时间里看到过很多Perl抨击,这只是作为程序员的几年。 Perl是一个很棒的语言,由一个非常聪明的语言学家(拉里·沃尔)制作,并且有一个狂热的追随者 - 一次比Ruby更狂热,也许,但不像David Koresh那么多。 Perl的工作方式与许多语言完全不同,但是如果你看看这个网站上的代码高尔夫条目和其他语言,你可以清楚地看到很多可以用很少的Perl完成(不保证代码易读性,特别是对于新手!)

答案 2 :(得分:5)

对象的bless值正在使用特定包中的方法。

package MyClass;
sub answer { my ($self)=@_; return $self->{foo} * 42; }

package main;
my $object1 = { foo => 1, bar => "\t" };
my $object2 = bless { foo => 2, bar => "\t" }, "MyClass";

$ref1 = ref $object1;        #  'HASH'
$ref2 = ref $object2;        #  'MyClass'

$answer1 = $object1->answer;     # run time error
$answer2 = $object2->answer;     # calls MyClass::answer, returns 2 * 42 = 84

答案 3 :(得分:4)

呃...... Sinan的回答完全是我的口味,至少在凌晨12点才开始学习:)。

因此,为了各种各样的缘故,我会给出一个更短,更少Perly的那个。

就我所知,你的问题并不是真的关于Perl ,并且可以像另一种形式一样轻松:“当C已经有结构时,为什么还要使用C ++和OOP? “

换句话说,你似乎在问我们使用OOP范式的重点是什么。

答案当然是它比纯程序编程更容易解​​决某些软件工程问题。强调某些 - OOP不是解决每个问题的灵丹妙药,不过是任何技术/方法/范例。

使用OOP(以包的形式作为类和祝福的哈希作为Perl中的对象)可以让您享受继承,多态和其他OOPyish mumbo-jumbo的好处,您可能已经非常熟悉非Perl OOP经验。

对于纯数据结构的祝福对象,你能做到100%吗?绝对。 100%的代码是否与使用对象一样容易/简短/可读/可维护的代码?最有可能的不是,虽然它取决于你的OOP代码实际上利用OOP提供的好处(BTW,我已经遇到了所谓的OOP代码(Perl而不是),这实际上并没有带来任何优势) OOP范例如果被剥离了OOP chrome,本来可以更容易阅读和理解。